/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = sqlserver_token.c                                             */
/*  NOTE      = TDS 请求解析                                                  */
/*  DATE      = 2014/09/30 by zhengxd                                         */
/******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "sqlserver_common.h"
#include "sqlserver_token.h"

/* 是否是最后一个DONE */
#define MSSQL_DONE_MORE                  0
#define MSSQL_DONE_FINAL                 1

#define MSSQL_ENV_TYPE_DATABASE          1   /* Database */
#define MSSQL_ENV_TYPE_LANGUAGE          2   /* Language */
#define MSSQL_ENV_TYPE_CHARSET           3   /* Character set */
#define MSSQL_ENV_TYPE_PACKET            4   /* Packet size */
#define MSSQL_ENV_TYPE_UCS2ID            5   /* Unicode data sorting local id */
#define MSSQL_ENV_TYPE_UCS2FLG           6   /* Unicode data sorting comparison flags */
#define MSSQL_ENV_TYPE_SQL               7   /* SQL Collation */
#define MSSQL_ENV_TYPE_BGEINTRANS        8   /* Begin Transaction (described in [MSDN-BEGIN]) */
#define MSSQL_ENV_TYPE_COMMITTRANS       9   /* Commit Transaction (described in [MSDN-COMMIT]) */
#define MSSQL_ENV_TYPE_ROLLBACKTRANS     10  /* Rollback Transaction */
#define MSSQL_ENV_TYPE_DTCTRANS          11  /* Enlist DTC Transaction */
#define MSSQL_ENV_TYPE_DEFECTTRANS       12  /* Defect Transaction */
#define MSSQL_ENV_TYPE_LOG               13  /* Real Time Log Shipping */
#define MSSQL_ENV_TYPE_PROMOTETRANS      15  /* Promote Transaction */
#define MSSQL_ENV_TYPE_TRANSADDR         16  /* Transaction Manager Address<15> */
#define MSSQL_ENV_TYPE_TRANSEND          17  /* Transaction ended */
#define MSSQL_ENV_TYPE_ACKNOWLEDGEMENT   18  /* RESETCONNECTION/RESETCONNECTIONSKIPTRAN Completion Acknowledgement */
#define MSSQL_ENV_TYPE_NAME              19  /* Sends back name of user instance started per login request */
#define MSSQL_ENV_TYPE_ROUTING           20  /* Sends routing information to client */

/*******************************************************************************
*  FUNC     :  做成type info链表
*  ARGS     :  uc_tds_data_type (TDS数据类型)
*           :  ui_precision(precision)
*           :  ui_scale(scale)
*           :  i_plp_flg(plp标记)
*           :  p_lst_header(链表头节点)
*  RTN      :  FR_SUCC   (success)
*              FR_FAIL   (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __sqlserver_add_metadata(unsigned char uc_tds_data_type
                                   , unsigned int ui_precision
                                   , unsigned int ui_scale
                                   , int i_plp_flg
                                   , Frlist_header *p_lst_header)
{
    int i_ret = FR_SUCC;
    Sql_metadata_info *p_st_metadata = NULL;

    /* 创建metadata */
    p_st_metadata = (Sql_metadata_info *)frmalloc(sizeof(Sql_metadata_info));
    if (p_st_metadata == NULL)
    {
        return FR_FAIL;
    }
    memset(p_st_metadata, 0x0, sizeof(Sql_metadata_info));
    /* 设置结构体值 */
    p_st_metadata->i_data_type = uc_tds_data_type;
    p_st_metadata->ui_precision = ui_precision;
    p_st_metadata->ui_scale = ui_scale;
    p_st_metadata->i_mssql_plp_flg = i_plp_flg;

    /* 追加节点 */
    i_ret = sqlserver_data_push(p_lst_header, p_st_metadata);
    if (i_ret != FR_SUCC)
    {
        frdb_metadata_free(&p_st_metadata);
        return FR_FAIL;
    }

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  追加altmetadata节点
*  ARGS     :  us_id (altmetadata id)
*           :  p_lst_metadata_header(metadata list)
*           :  p_lst_altmetadata_header(altmetadata list)
*  RTN      :  FR_SUCC       (normal)
*              FR_FAIL       (error)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __sqlserver_add_altmetadata(unsigned short us_id
                                      , Frlist_header *p_lst_metadata_header
                                      , Frlist_header *p_lst_altmetadata_header)
{
    int i_ret = FR_SUCC;
    Mssql_altmetadata_info *p_st_altmetadata = NULL;

    /* 创建altmetadata */
    p_st_altmetadata = (Mssql_altmetadata_info *)frmalloc(sizeof(Mssql_altmetadata_info));
    if (p_st_altmetadata == NULL)
    {
        return FR_FAIL;
    }
    memset(p_st_altmetadata, 0x0, sizeof(Mssql_altmetadata_info));
    /* 设置结构体值 */
    p_st_altmetadata->us_id = us_id;
    p_st_altmetadata->p_lst_metadata = p_lst_metadata_header;

    /* 追加节点 */
    i_ret = sqlserver_data_push(p_lst_altmetadata_header, p_st_altmetadata);
    if (i_ret != FR_SUCC)
    {
        frfree(p_st_altmetadata);
        return FR_FAIL;
    }

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  跳过part name
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __sqlserver_skip_partname(Frbyte_Packet *p_st_data, int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint8_t u8_num_part = 0;
    unsigned int ui_value_len = 0;
    char *p_value = NULL;

    /* 取得NumParts */
    if (bytebuff_remaining(p_st_data) < MSSQL_TDS_BYTE_LEN)
    {
         goto error;
    }
    /* 取得长度位,并跳过 */
    bytebuff_get_char(p_st_data, &u8_num_part);

    /* 根据协议至少要有一个part name */
    if (u8_num_part == 0)
    {
         return APM_L7_ANALYZE_FAIL;
    }

    /* 遍历part name */
    while (u8_num_part--)
    {
        /* 跳过TableName */
        i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg, APM_TDS_US_VARCHAR
                                      , FR_NO, &p_value, &ui_value_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            return i_ret;
        }
    }

    /* 设置出力 */
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析
*  ARGS     :  p_st_data(数据)
*           :  i_whole_flg(packet完整flag)
*           :  p_i_tds_ver(TDS版本号)
*           :  p_i_min_tds_ver(可能最小版本号)
*           :  p_i_max_tds_ver(可能最大版本号)
*           :  p_i_try_again_flg(该token是在未定义的情况下解析的，
*                             外围如果解析出错可能需要用高一级版本再解析一遍)
*           :  p_lst_altmetadata(ALTMETADATA链表)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :  p_lst_altmetadata必须不为NULL,且失败需要释放
*******************************************************************************/
int sqlserver_altmetadata_token(Frbyte_Packet *p_st_data
                                , int i_whole_flg
                                , int *p_i_tds_ver
                                , int *p_i_min_tds_ver
                                , int *p_i_max_tds_ver
                                , int *p_i_try_again_flg
                                , Frlist_header *p_lst_altmetadata)
{
    /* 定义：
    * ALTMETADATA = TokenType
    *               Count
    *               Id
    *               ByCols
    *               *<ByCols>ColNum
    *               1* ComputeData
    * ComputeData = Op
    *               Operand
    *               UserType
    *               Flags
    *               TYPE_INFO
    *               [TableName]
    *               ColName
    */
    int i_ret = FR_SUCC;
    int i_ver_flg = MSSQL_TDS_VER_UNKNOWN;
    int i_min_tds_ver = *p_i_min_tds_ver;
    int i_max_tds_ver = *p_i_max_tds_ver;
    int i_plp_flg = FR_NO;
    uint8_t u8_tds_data_type = 0;
    uint16_t u16_id = 0;
    uint16_t u16_count = 0;
    uint16_t u16_count_tmp = 0;
    uint8_t u8_bycols = 0;
    uint8_t u8_scale = 0;
    uint8_t u8_precision = 0;
    unsigned int ui_column_len = 0;
    unsigned int ui_value_len = 0;
    unsigned int ui_position = 0;
    char *p_value = NULL;
    Frlist_header *p_lst_metadata = NULL;
    char arr_buff[2] = {0};

    /* 取得Count */
    if (bytebuff_remaining(p_st_data) < MSSQL_TDS_USHORT_LEN)
    {
        goto error;
    }
    i_ret = bytebuff_get_short(p_st_data, MSSQL_TDS_USHORT_LEN
                               , &u16_count, BYTE_LITTLE_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 取到ID */
    if (bytebuff_remaining(p_st_data) < MSSQL_TDS_USHORT_LEN)
    {
        goto error;
    }
    i_ret = bytebuff_get_short(p_st_data, MSSQL_TDS_USHORT_LEN
                              , &u16_id, BYTE_LITTLE_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 取到ByCols */
    if (bytebuff_remaining(p_st_data) < MSSQL_TDS_UCHAR_LEN)
    {
        goto error;
    }
    bytebuff_get_char(p_st_data, &u8_bycols);

    /* 跳过ColNum */
    ui_column_len = u8_bycols * 2;
    if (ui_column_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        goto error;
    }
    bytebuff_skip(p_st_data, ui_column_len);

    /* 创建header */
    p_lst_metadata = frlist_create();
    if (p_lst_metadata == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 解析ComputeData */
    u16_count_tmp = u16_count;
    ui_position = bytebuff_getPosition(p_st_data);
    while (u16_count_tmp--)
    {
        /* 跳过Op Operand */
        if (bytebuff_remaining(p_st_data) < MSSQL_TDS_BYTE_LEN + MSSQL_TDS_USHORT_LEN)
        {
            if (i_whole_flg == FR_YES)
            {
                /* 假如在TDS版本号未定的情况下，用较低版本解析出错,可尝试再用较高版本解析 */
                if (i_ver_flg == MSSQL_TDS_VER_LITTLE)
                {
                    /* 初始化 */
                    frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                    u16_count_tmp = u16_count;
                    bytebuff_setPosition(p_st_data, ui_position);
                    i_ver_flg = MSSQL_TDS_VER_BIG;
                    continue;
                }
                else
                {
                    frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
                    return APM_L7_ANALYZE_FAIL;
                }
            }
            else
            {
                frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
                return APM_L7_ANALYZE_TODO;
            }
        }
        bytebuff_skip(p_st_data, MSSQL_TDS_BYTE_LEN + MSSQL_TDS_USHORT_LEN);

        /* UserType = USHORT/ULONG; (changed to ULONG in TDS 7.2) */
        /* TDS版本号小于7.2 */
        if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && i_max_tds_ver <= MSSQL_TDS_VER_71R1)
             || (*p_i_tds_ver != MSSQL_TDS_VER_NULL && *p_i_tds_ver <= MSSQL_TDS_VER_71R1))
        {
            /* UserType = USHORT */
            if (bytebuff_remaining(p_st_data) < MSSQL_TDS_USHORT_LEN)
            {
                frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
                goto error;
            }
            bytebuff_skip(p_st_data, MSSQL_TDS_USHORT_LEN);
        }
        /* TDS版本号大于等于于7.2 */
        else if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && i_min_tds_ver >= MSSQL_TDS_VER_72)
                  || (*p_i_tds_ver >= MSSQL_TDS_VER_72))
        {
            /* UserType = ULONG */
            if (bytebuff_remaining(p_st_data) < MSSQL_TDS_ULONG_LEN)
            {
                frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
                goto error;
            }
            bytebuff_skip(p_st_data, MSSQL_TDS_ULONG_LEN);
        }
        /* TDS版本号不定 */
        else
        {
            /* 先用低版本解析 */
            if (i_ver_flg == MSSQL_TDS_VER_UNKNOWN || i_ver_flg == MSSQL_TDS_VER_LITTLE)
            {
                /* UserType = USHORT */
                if (bytebuff_remaining(p_st_data) < MSSQL_TDS_USHORT_LEN)
                {
                    if (i_whole_flg == FR_YES)
                    {
                        /* 初始化 */
                        frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                        u16_count_tmp = u16_count;
                        bytebuff_setPosition(p_st_data, ui_position);
                        i_ver_flg = MSSQL_TDS_VER_BIG;
                        continue;
                    }
                    else
                    {
                        frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
                        return APM_L7_ANALYZE_TODO;
                    }
                }
                i_ver_flg = MSSQL_TDS_VER_LITTLE;
                bytebuff_skip(p_st_data, MSSQL_TDS_USHORT_LEN);
            }
            else
            {
                /* UserType = ULONG */
                if (bytebuff_remaining(p_st_data) < MSSQL_TDS_ULONG_LEN)
                {
                    frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
                    goto error;
                }
                bytebuff_skip(p_st_data, MSSQL_TDS_ULONG_LEN);
            }
        }

        /* 解析options */
        if (bytebuff_remaining(p_st_data) < 2)
        {
            /* 假如在TDS版本号未定的情况下，用较低版本解析出错，可尝试再用较高版本解析 */
            if (i_ver_flg == MSSQL_TDS_VER_LITTLE)
            {
                if (i_whole_flg == FR_YES)
                {
                    /* 初始化 */
                    frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                    u16_count_tmp = u16_count;
                    bytebuff_setPosition(p_st_data, ui_position);
                    i_ver_flg = MSSQL_TDS_VER_BIG;
                    continue;
                }
                else
                {
                    frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
                    return APM_L7_ANALYZE_TODO;
                }
            }
            else
            {
                frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
                goto error;
            }
        }

        i_ret = bytebuff_peek_bytes(p_st_data, arr_buff, 2);
        if (i_ret != FR_SUCC)
        {
            frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        /* fComputed = BIT ; (introduced in TDS 7.2) */
        /* fFixedLenCLRType = BIT ; (introduced in TDS 7.2) */
        if (arr_buff[0] & 0x04 || arr_buff[1] & 0x80)
        {
            /* 版本是7.2以下却有7.2以上才有的数据 */
            if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && i_max_tds_ver <= MSSQL_TDS_VER_71R1)
                 || (*p_i_tds_ver != MSSQL_TDS_VER_NULL && *p_i_tds_ver <= MSSQL_TDS_VER_71R1))
            {
                frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
                return APM_L7_ANALYZE_FAIL;
            }
            /* 当前使用较低版本解析 */
            else if (i_ver_flg == MSSQL_TDS_VER_LITTLE)
            {
                /* 初始化化 */
                frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                u16_count_tmp = u16_count;
                bytebuff_setPosition(p_st_data, ui_position);
                i_ver_flg = MSSQL_TDS_VER_BIG;
                continue;
            }
            else if (*p_i_tds_ver == MSSQL_TDS_VER_NULL && i_min_tds_ver < MSSQL_TDS_VER_72)
            {
                i_min_tds_ver = MSSQL_TDS_VER_72;
            }
        }

        /* skip Flags */
        bytebuff_skip(p_st_data, 2);
        /* 解析type info */
        i_ret = sqlserver_type_info_parse(p_st_data, i_whole_flg, MSSQL_COLMETA
                                          , &i_min_tds_ver, &u8_tds_data_type
                                          , &u8_precision, &u8_scale
                                          , &i_plp_flg);
        if (i_ret == APM_L7_ANALYZE_FAIL)
        {
            /* 假如在TDS版本号未定的情况下，用较低版本解析出错，可尝试再用较高版本解析 */
            if (i_ver_flg == MSSQL_TDS_VER_LITTLE)
            {
                /* 初始化 */
                frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                u16_count_tmp = u16_count;
                bytebuff_setPosition(p_st_data, ui_position);
                i_ver_flg = MSSQL_TDS_VER_BIG;
                continue;
            }
            frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        else if (i_ret == APM_L7_ANALYZE_TODO)
        {
            frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_TODO;
        }

        /* 当版本取得版本较大时，需要判断是否符合格式 */
        if (i_min_tds_ver >= MSSQL_TDS_VER_72)
        {
            /* 入力参数指定TDS版本号是小于7.2的 */
            if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && i_max_tds_ver <= MSSQL_TDS_VER_71R1)
                 || (*p_i_tds_ver != MSSQL_TDS_VER_NULL && *p_i_tds_ver <= MSSQL_TDS_VER_71R1))
            {
                frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
                goto error;
            }
            /* 假如在TDS版本号未定的情况下，用较低版本解析出错，可尝试再用较高版本解析 */
            else if (i_ver_flg == MSSQL_TDS_VER_LITTLE)
            {
                /* 初始化 */
                frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                u16_count_tmp = u16_count;
                bytebuff_setPosition(p_st_data, ui_position);
                i_ver_flg = MSSQL_TDS_VER_BIG;
                continue;
            }
        }

        /* 做成metadata链表 */
        i_ret = __sqlserver_add_metadata(u8_tds_data_type, u8_precision
                                        , u8_scale, i_plp_flg, p_lst_metadata);
        if (i_ret != FR_SUCC)
        {
            frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }

        /* TableName field SHOULD never be sent because SQL statements that generate totals exclude NTEXT/TEXT/IMAGE */
        if (u8_tds_data_type == TDS_DATA_TYPE_TEXT
            || u8_tds_data_type == TDS_DATA_TYPE_NTEXT
            || u8_tds_data_type == TDS_DATA_TYPE_IMAGE)
        {
            /* US_VARCHAR ; (removed in TDS 7.2) */
            if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && i_max_tds_ver <= MSSQL_TDS_VER_71R1)
                 || (*p_i_tds_ver != MSSQL_TDS_VER_NULL && *p_i_tds_ver <= MSSQL_TDS_VER_71R1))
            {
                /* 跳过TableName */
                i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg
                                              , APM_TDS_US_VARCHAR, FR_NO
                                              , &p_value, &ui_value_len);
                if (i_ret == APM_L7_ANALYZE_FAIL)
                {
                    frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
                    return APM_L7_ANALYZE_FAIL;
                }
                else if (i_ret == APM_L7_ANALYZE_TODO)
                {
                    frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
                    return APM_L7_ANALYZE_TODO;
                }
            }
            /* (NumParts 1*PartName) ; (introduced in TDS 7.2) */
            else if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && i_min_tds_ver >= MSSQL_TDS_VER_72)
                      || (*p_i_tds_ver >= MSSQL_TDS_VER_72) || (i_ver_flg == MSSQL_TDS_VER_BIG))
            {
                /* 跳过part name */
                if (i_ret == APM_L7_ANALYZE_FAIL)
                {
                    frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
                    return APM_L7_ANALYZE_FAIL;
                }
                else if (i_ret == APM_L7_ANALYZE_TODO)
                {
                    frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
                    return APM_L7_ANALYZE_TODO;
                }
            }
            /* 版本未知，用小版本解析 */
            else
            {
                /* 跳过TableName */
                i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg
                                              , APM_TDS_US_VARCHAR, FR_NO
                                              , &p_value, &ui_value_len);
                if (i_ret == APM_L7_ANALYZE_FAIL)
                {
                    /* 初始化 */
                    frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                    u16_count_tmp = u16_count;
                    bytebuff_setPosition(p_st_data, ui_position);
                    i_ver_flg = MSSQL_TDS_VER_BIG;
                    continue;
                }
                else if (i_ret == APM_L7_ANALYZE_TODO)
                {
                    frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
                    return APM_L7_ANALYZE_TODO;
                }
            }
        }

        /* 解析ColName */
        i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg, APM_TDS_B_VARCHAR
                                      , FR_NO , &p_value, &ui_value_len);
        if (i_ret == APM_L7_ANALYZE_FAIL)
        {
            /* 假如在TDS版本号未定的情况下，用较低版本解析出错，可尝试再用较高版本解析 */
            if (i_ver_flg == MSSQL_TDS_VER_LITTLE)
            {
                frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                u16_count_tmp = u16_count;
                bytebuff_setPosition(p_st_data, ui_position);
                i_ver_flg = MSSQL_TDS_VER_BIG;
                continue;
            }
            frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        else if (i_ret == APM_L7_ANALYZE_TODO)
        {
            frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_TODO;
        }
    }

    /* 做成altmetadata结构 */
    i_ret = __sqlserver_add_altmetadata(u16_id, p_lst_metadata
                                       , p_lst_altmetadata);
    if (i_ret != FR_SUCC)
    {
        frlist_destroy(p_lst_metadata, frdb_metadata_node_free);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 在版本未知的情况下，用小版本解析正确 */
    if (i_ver_flg == MSSQL_TDS_VER_LITTLE)
    {
        *p_i_max_tds_ver = MSSQL_TDS_VER_71R1;
        *p_i_try_again_flg = FR_YES;
    }
    else if (i_ver_flg == MSSQL_TDS_VER_BIG && *p_i_tds_ver == MSSQL_TDS_VER_NULL)
    {
        *p_i_min_tds_ver = i_min_tds_ver > MSSQL_TDS_VER_72 ? i_min_tds_ver : MSSQL_TDS_VER_72;
    }
    /* 最大最小值一样 */
    if (*p_i_tds_ver == MSSQL_TDS_VER_NULL && *p_i_max_tds_ver == *p_i_min_tds_ver)
    {
        *p_i_tds_ver = *p_i_max_tds_ver;
    }
    /* 设置出力 */
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析
*  ARGS     :  p_st_data(数据)
*           :  i_whole_flg(packet完整flag)
*           :  p_lst_altmetadata(ALTMETADATA链表)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_altrow_token(Frbyte_Packet *p_st_data
                           , int i_whole_flg
                           , Frlist_header *p_lst_altmetadata)
{
    /* 定义：
    * ALTMETADATA = TokenType
    *               Id
    *               1*ComputeData
    */
    int i_ret = FR_SUCC;
    uint16_t u16_id = 0;
    Frlist_node *p_st_node = NULL;
    Mssql_altmetadata_info *p_st_altmetadata = NULL;
    Frlist_header *p_lst_metadata = NULL;
    Sql_metadata_info *p_st_metadata = NULL;

    /* 取得ID */
    if (bytebuff_remaining(p_st_data) < MSSQL_TDS_USHORT_LEN)
    {
        goto error;
    }
    i_ret = bytebuff_get_short(p_st_data, MSSQL_TDS_USHORT_LEN
                               , &u16_id, BYTE_LITTLE_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 取得对应id的节点 */
    p_st_node = FRLIST_FIRST_NODE(p_lst_altmetadata);
    while(p_st_node)
    {
        p_st_altmetadata = (Mssql_altmetadata_info *)FRLIST_GET_NODE_DATA(p_st_node);
        if (p_st_altmetadata->us_id == u16_id)
        {
            p_lst_metadata = p_st_altmetadata->p_lst_metadata;
            break;
        }
        p_st_node = FRLIST_NEXT_NODE(p_st_node);
    }
    /* 没有对应节点 */
    if (p_lst_metadata == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    p_st_node = FRLIST_FIRST_NODE(p_lst_metadata);
    /* 解析AllColumnData, 每个metadata节点对应一个ColumnData */
    while (p_st_node)
    {
        p_st_metadata = (Sql_metadata_info *)FRLIST_GET_NODE_DATA(p_st_node);
        /* 解析Data = TYPE_VARBYTE */
        i_ret = sqlserver_skip_type_varbyte(p_st_data, i_whole_flg
                                           , p_st_metadata->i_data_type
                                           , p_st_metadata->ui_scale
                                           , p_st_metadata->ui_precision
                                           , p_st_metadata->i_mssql_plp_flg);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            return i_ret;
        }
        p_st_node = FRLIST_NEXT_NODE(p_st_node);
    }

    /* 设置出力参数 */
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析
*  ARGS     :  p_st_data(数据)
*           :  i_whole_flg(packet完整flag)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_colinfo_token(Frbyte_Packet *p_st_data, int i_whole_flg)
{
    /* 定义：
    * COLINFO = TokenType
    *           Length
    *           1*CpLProperty
    * ColProperty = ColNum
    *               TableNum
    *               Status
    *               [ColName]
    */
    int i_ret = FR_SUCC;
    uint8_t u8_status = 0;
    uint16_t u16_token_len = 0;
    unsigned int ui_value_len = 0;
    unsigned int ui_position1 = 0;
    unsigned int ui_position2 = 0;
    char *p_value = NULL;

    /* 取得token长度 */
    if (bytebuff_remaining(p_st_data) < MSSQL_TDS_USHORT_LEN)
    {
        goto error;
    }
    i_ret = bytebuff_get_short(p_st_data, MSSQL_TDS_USHORT_LEN
                               , &u16_token_len, BYTE_LITTLE_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 至少有一个CpLProperty,所以token长度不可能为0 */
    if (u16_token_len == 0 )
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (u16_token_len > bytebuff_remaining(p_st_data))
    {
        goto error;
    }

    /* 解析CpLProperty */
    while (u16_token_len)
    {
        if (u16_token_len < MSSQL_TDS_BYTE_LEN + MSSQL_TDS_BYTE_LEN + MSSQL_TDS_BYTE_LEN)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        /* 跳过ColNum TableNum */
        bytebuff_skip(p_st_data, MSSQL_TDS_BYTE_LEN + MSSQL_TDS_BYTE_LEN);
        u16_token_len -= MSSQL_TDS_BYTE_LEN + MSSQL_TDS_BYTE_LEN;
        /* Base column name only occurs if DIFFERENT_NAME is set in Status. */
        bytebuff_get_char(p_st_data, &u8_status);
        if (u8_status == 0x20)
        {
            /* 跳过Status */
            u16_token_len -= MSSQL_TDS_BYTE_LEN;
            /* 跳过ColName */
            ui_position1 = bytebuff_getPosition(p_st_data);
            i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg, APM_TDS_B_VARCHAR
                                          , FR_NO, &p_value, &ui_value_len);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            ui_position2 = bytebuff_getPosition(p_st_data);
            u16_token_len -= ui_position2 - ui_position1;
        }
        else
        {
            /* 跳过Status */
            u16_token_len -= MSSQL_TDS_BYTE_LEN;
        }
    }

    /* 设置出力 */
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析colmetadata token
*  ARGS     :  p_st_data(数据)
*           :  i_whole_flg(packet完整flag)
*           :  p_i_tds_ver(TDS版本号)
*           :  p_i_min_tds_ver(可能最小版本号)
*           :  p_i_max_tds_ver(可能最大版本号)
*           :  p_i_try_again_flg(该token是在未定义的情况下解析的，
*                             外围如果解析出错可能需要用高一级版本再解析一遍)
*           :  pp_st_colmetadata_info(COLMETADATA结构体)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_colmetadata_token(Frbyte_Packet *p_st_data
                                , int i_whole_flg
                                , int *p_i_tds_ver
                                , int *p_i_min_tds_ver
                                , int *p_i_max_tds_ver
                                , int *p_i_try_again_flg
                                , Frlist_header *p_lst_metadata)
{
    /*
    * COLMETADATA = TokenType
    *               Count
    *               NoMetaData / (1 *ColumnData)
    * ColumnData = UserType
    *              Flags
    *              TYPE_INFO
    *              [TableName]
    *              ColName
    */
    int i_ret = FR_SUCC;
    int i_plp_flg = FR_NO;
    int i_ver_flg = MSSQL_TDS_VER_UNKNOWN;
    int i_min_tds_ver = *p_i_min_tds_ver;
    int i_max_tds_ver = *p_i_max_tds_ver;
    uint8_t u8_tds_data_type = 0;
    uint16_t u16_row_count = 0;
    uint16_t u16_row_count_tmp = 0;
    uint8_t u8_precision = 0;
    uint8_t u8_scale = 0;
    unsigned int ui_value_len = 0;
    unsigned int ui_position = 0;
    char *p_value = NULL;
    char arr_buff[2] = {0};

    /* 取得列数(Count) */
    if (bytebuff_remaining(p_st_data) < MSSQL_TDS_USHORT_LEN)
    {
        goto error;
    }

    i_ret = bytebuff_peek_bytes(p_st_data, arr_buff, 2);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 判断是否是空列(NoMetaData) */
    if ((unsigned char)arr_buff[0] == 0xFF && (unsigned char)arr_buff[1] == 0xFF)
    {
        bytebuff_skip(p_st_data, 2);
        return APM_L7_ANALYZE_SUCC;
    }

    i_ret = bytebuff_get_short(p_st_data, MSSQL_TDS_USHORT_LEN
                               , &u16_row_count, BYTE_LITTLE_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 至少会有一个NoMetaData(2byte) */
    if (bytebuff_remaining(p_st_data) < 2)
    {
        goto error;
    }

    /* 有协议可知count数至少有一个 */
    if (u16_row_count == 0)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    u16_row_count_tmp = u16_row_count;
    ui_position = bytebuff_getPosition(p_st_data);
    /* 遍历ColumnData */
    while (u16_row_count_tmp--)
    {
        /* 跳过UserType,UserType = USHORT/ULONG; (Changed to ULONG in TDS 7.2) */
        /* UserType = USHORT/ULONG; (changed to ULONG in TDS 7.2) */
        /* TDS版本号小于7.2 */
        if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && i_max_tds_ver <= MSSQL_TDS_VER_71R1)
             || (*p_i_tds_ver != MSSQL_TDS_VER_NULL && *p_i_tds_ver <= MSSQL_TDS_VER_71R1))
        {
            /* UserType = USHORT */
            if (bytebuff_remaining(p_st_data) < MSSQL_TDS_USHORT_LEN)
            {
                frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                goto error;
            }
            bytebuff_skip(p_st_data, MSSQL_TDS_USHORT_LEN);
        }
        /* TDS版本号大于等于于7.2 */
        else if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && i_min_tds_ver >= MSSQL_TDS_VER_72)
                  || (*p_i_tds_ver >= MSSQL_TDS_VER_72))
        {
            /* UserType = ULONG */
            if (bytebuff_remaining(p_st_data) < MSSQL_TDS_ULONG_LEN)
            {
                frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                goto error;
            }
            bytebuff_skip(p_st_data, MSSQL_TDS_ULONG_LEN);
        }
        /* TDS版本号不定 */
        else
        {
            /* 先用低版本解析 */
            if (i_ver_flg == MSSQL_TDS_VER_UNKNOWN || i_ver_flg == MSSQL_TDS_VER_LITTLE)
            {
                /* UserType = USHORT */
                if (bytebuff_remaining(p_st_data) < MSSQL_TDS_USHORT_LEN)
                {
                    /* 初始化 */
                    frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                    if (i_whole_flg == FR_YES)
                    {
                        u16_row_count_tmp = u16_row_count;
                        bytebuff_setPosition(p_st_data, ui_position);
                        i_ver_flg = MSSQL_TDS_VER_BIG;
                        continue;
                    }
                    else
                    {
                        return APM_L7_ANALYZE_TODO;
                    }
                }
                i_ver_flg = MSSQL_TDS_VER_LITTLE;
                bytebuff_skip(p_st_data, MSSQL_TDS_USHORT_LEN);
            }
            else
            {
                /* UserType = ULONG */
                if (bytebuff_remaining(p_st_data) < MSSQL_TDS_ULONG_LEN)
                {
                    frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                    goto error;
                }
                bytebuff_skip(p_st_data, MSSQL_TDS_ULONG_LEN);
            }
        }

        /* 解析flags */
        if (bytebuff_remaining(p_st_data) < 2)
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            /* 假如在TDS版本号未定的情况下，用较低版本解析出错，可尝试再用较高版本解析 */
            if (i_ver_flg == MSSQL_TDS_VER_LITTLE)
            {
                /* 初始化 */
                if (i_whole_flg == FR_YES)
                {
                    u16_row_count_tmp = u16_row_count;
                    bytebuff_setPosition(p_st_data, ui_position);
                    i_ver_flg = MSSQL_TDS_VER_BIG;
                    continue;
                }
                else
                {
                    return APM_L7_ANALYZE_TODO;
                }
            }
            goto error;
        }


        /* 取得Flags */
        i_ret = bytebuff_get_bytes(p_st_data, arr_buff, 2);
        if (i_ret != FR_SUCC)
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }
        /*
        * fComputed = BIT ; (introduced in TDS 7.2)
        *  fFixedLenCLRType = BIT ; (introduced in TDS 7.2)
        *  fHidden = BIT ; (introduced in TDS 7.2)
        *  fKey = BIT ; (introduced in TDS 7.2)
        *  fNullableUnknown = BIT ; (introduced in TDS 7.2)
        */
        if (arr_buff[0] & 0x04 || arr_buff[1] & 0x08 || arr_buff[1] & 0x04
            || arr_buff[1] & 0x02 || arr_buff[1] & 0x01)
        {
            /* 实际使用版本号小于7.2 */
            if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && i_max_tds_ver <= MSSQL_TDS_VER_71R1)
                 || (*p_i_tds_ver != MSSQL_TDS_VER_NULL && *p_i_tds_ver <= MSSQL_TDS_VER_71R1))
            {
                frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                return APM_L7_ANALYZE_FAIL;
            }
            /* 当前使用较低版本解析 */
            else if (i_ver_flg == MSSQL_TDS_VER_LITTLE)
            {
                frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                u16_row_count_tmp = u16_row_count;
                bytebuff_setPosition(p_st_data, ui_position);
                i_ver_flg = MSSQL_TDS_VER_BIG;
                continue;
            }
        }

        /*
        * fSparseColumnSet = BIT ; (introduced in TDS 7.3.B)
        *  usReserved2 = 2BIT ; (introduced in TDS 7.3.B)
        */
        if (arr_buff[1] & 0x40 || arr_buff[1] & 0x30)
        {
            /* 实际使用版本号小于7.3 */
            if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && i_max_tds_ver <= MSSQL_TDS_VER_73A)
                 || (*p_i_tds_ver != MSSQL_TDS_VER_NULL && *p_i_tds_ver <= MSSQL_TDS_VER_73A))
            {
                frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                return APM_L7_ANALYZE_FAIL;
            }
            /* 当前使用较低版本解析 */
            else if (i_ver_flg == MSSQL_TDS_VER_LITTLE)
            {
                frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                u16_row_count_tmp = u16_row_count;
                bytebuff_setPosition(p_st_data, ui_position);
                i_ver_flg = MSSQL_TDS_VER_BIG;
                continue;
            }
        }

        /* usReservedODBC = 2BIT ; (only exists in TDS 7.3.A and below) */
        if (arr_buff[0] & 0x03)
        {
            if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && i_min_tds_ver >= MSSQL_TDS_VER_73B)
                 || (*p_i_tds_ver >= MSSQL_TDS_VER_73B))
            {
                frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                return APM_L7_ANALYZE_FAIL;
            }
        }

        /* 解析type info */
        i_ret = sqlserver_type_info_parse(p_st_data, i_whole_flg, MSSQL_COLMETA
                                         , &i_min_tds_ver, &u8_tds_data_type
                                         , &u8_precision, &u8_scale
                                         , &i_plp_flg);
        if (i_ret == APM_L7_ANALYZE_FAIL)
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            /* 假如在TDS版本号未定的情况下，用较低版本解析出错，可尝试再用较高版本解析 */
            if (i_ver_flg == MSSQL_TDS_VER_LITTLE)
            {
                u16_row_count_tmp = u16_row_count;
                bytebuff_setPosition(p_st_data, ui_position);
                i_ver_flg = MSSQL_TDS_VER_BIG;
                continue;
            }
            return APM_L7_ANALYZE_FAIL;
        }
        else if (i_ret == APM_L7_ANALYZE_TODO)
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_TODO;
        }

        i_ret = __sqlserver_add_metadata(u8_tds_data_type, u8_precision
                                        , u8_scale, i_plp_flg, p_lst_metadata);
        if (i_ret != FR_SUCC)
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_FAIL;
        }

        /* 当版本取得版本较大时，需要判断是否符合格式 */
        if (i_min_tds_ver >= MSSQL_TDS_VER_72)
        {
            /* 入力参数指定TDS版本号是小于7.2的 */
            if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && i_max_tds_ver <= MSSQL_TDS_VER_71R1)
                 || (*p_i_tds_ver != MSSQL_TDS_VER_NULL && *p_i_tds_ver <= MSSQL_TDS_VER_71R1))
            {
                frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                return APM_L7_ANALYZE_FAIL;
            }
            /* 当前是在较低版本下解析的 */
            else if (i_ver_flg == MSSQL_TDS_VER_LITTLE)
            {
                frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                u16_row_count_tmp = u16_row_count;
                bytebuff_setPosition(p_st_data, ui_position);
                i_ver_flg = MSSQL_TDS_VER_BIG;
                continue;
            }
        }

        /* TableName field SHOULD never be sent because SQL statements that generate totals exclude NTEXT/TEXT/IMAGE */
        if (u8_tds_data_type == TDS_DATA_TYPE_TEXT || u8_tds_data_type == TDS_DATA_TYPE_NTEXT
            || u8_tds_data_type == TDS_DATA_TYPE_IMAGE)
        {
            /* 注：此处与协议不一致，应该是协议书写错误 */
            /* US_VARCHAR ; (removed in TDS 7.2) */
            if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && i_max_tds_ver <= MSSQL_TDS_VER_71R1)
                 || (*p_i_tds_ver != MSSQL_TDS_VER_NULL && *p_i_tds_ver <= MSSQL_TDS_VER_71R1))
            {
                /* 跳过TableName */
                i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg
                                             , APM_TDS_US_VARCHAR, FR_NO
                                             , &p_value, &ui_value_len);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                    return i_ret;
                }
            }
            /* (NumParts 1*PartName) ; (introduced in TDS 7.2) */
            else if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && i_min_tds_ver >= MSSQL_TDS_VER_72)
                      || (*p_i_tds_ver >= MSSQL_TDS_VER_72) || (i_ver_flg == MSSQL_TDS_VER_BIG))
            {
                /* 跳过part name */
                i_ret = __sqlserver_skip_partname(p_st_data, i_whole_flg);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                    return i_ret;
                }
            }
            /* 版本未知，用小版本解析 */
            else
            {
                /* 跳过TableName */
                i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg
                                             , APM_TDS_US_VARCHAR, FR_NO
                                             , &p_value, &ui_value_len);
                if (i_ret == APM_L7_ANALYZE_FAIL)
                {
                    if (i_ver_flg == MSSQL_TDS_VER_LITTLE)
                    {
                        frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                        u16_row_count_tmp = u16_row_count;
                        bytebuff_setPosition(p_st_data, ui_position);
                        i_ver_flg = MSSQL_TDS_VER_BIG;
                        continue;
                    }
                    return APM_L7_ANALYZE_FAIL;
                }
                else if (i_ret == APM_L7_ANALYZE_TODO)
                {
                    frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
                    return APM_L7_ANALYZE_TODO;
                }
            }
        }

        /* 解析ColName */
        i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg, APM_TDS_B_VARCHAR
                                      , FR_NO , &p_value, &ui_value_len);
        /* ColName解析出错 */
        if (i_ret == APM_L7_ANALYZE_FAIL)
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            /* 假如在TDS版本号未定的情况下，用较低版本解析出错，可尝试再用较高版本解析 */
            if (i_ver_flg == MSSQL_TDS_VER_LITTLE)
            {
                u16_row_count_tmp = u16_row_count;
                bytebuff_setPosition(p_st_data, ui_position);
                i_ver_flg = MSSQL_TDS_VER_BIG;
                continue;
            }
            return APM_L7_ANALYZE_FAIL;
        }
        else if (i_ret == APM_L7_ANALYZE_TODO)
        {
            frlist_remove_all(p_lst_metadata, frdb_metadata_node_free);
            return APM_L7_ANALYZE_TODO;
        }
    }

    /* 在版本未知的情况下，用小版本解析正确 */
    if (i_ver_flg == MSSQL_TDS_VER_LITTLE)
    {
        *p_i_max_tds_ver = MSSQL_TDS_VER_71R1;
        *p_i_try_again_flg = FR_YES;
    }
    else if (i_ver_flg == MSSQL_TDS_VER_BIG && *p_i_tds_ver == MSSQL_TDS_VER_NULL)
    {
        *p_i_min_tds_ver = i_min_tds_ver > MSSQL_TDS_VER_72 ? i_min_tds_ver : MSSQL_TDS_VER_72;
    }
    /* 最大最小值一样 */
    if (*p_i_tds_ver == MSSQL_TDS_VER_NULL && *p_i_max_tds_ver == *p_i_min_tds_ver)
    {
        *p_i_tds_ver = *p_i_max_tds_ver;
    }
    /* 设置出力 */
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析row数据
*  ARGS     :  p_st_data(数据)
*           :  i_whole_flg(packet完整flag)
*           :  p_lst_metadata_header(metadata数据)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_row_token(Frbyte_Packet *p_st_data
                        , int i_whole_flg
                        , Frlist_header *p_lst_metadata)
{
    /*
    * ROW = TokenType
    *       AllColumnData
    * AllColumnData = *ColumnData
    * ColumnData = [TextPointer Timestamp]
    *              Data
    */
    int i_ret = FR_SUCC;
    uint8_t u8_tmp = 0;
    int i_data_type = 0;
    unsigned int ui_value_len = 0;
    char *p_value = NULL;
    Frlist_node *p_st_node = NULL;
    Sql_metadata_info *p_st_metadata = NULL;

    /* 解析AllColumnData, 每个metadata节点对应一个ColumnData */
    p_st_node = FRLIST_FIRST_NODE(p_lst_metadata);
    while (p_st_node)
    {
        p_st_metadata = (Sql_metadata_info *)FRLIST_GET_NODE_DATA(p_st_node);
        i_data_type = p_st_metadata->i_data_type;
        /*
        * TextPointer and Timestamp MUST NOT be specified if the instance of
        * type text/ntext/image is a NULL instance (GEN_NULL).
        */
        if (i_data_type == TDS_DATA_TYPE_TEXT
            || i_data_type == TDS_DATA_TYPE_NTEXT
            || i_data_type == TDS_DATA_TYPE_IMAGE)
        {
            bytebuff_peek_char(p_st_data, &u8_tmp);
            /* 不是GEN_NULL时，需要考虑[TextPointer Timestamp] */
            if (u8_tmp != '\0')
            {
                /* 跳过TextPointer = B_VARBYTE */
                i_ret = sqlserver_get_varbytes(p_st_data, i_whole_flg
                                              , APM_TDS_B_VARBYTE, FR_NO
                                              , &p_value, &ui_value_len);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    return i_ret;
                }
                /* 跳过Timestamp = 8BYTE */
                if (bytebuff_remaining(p_st_data) < 8)
                {
                   goto error;
                }
                bytebuff_skip(p_st_data, 8);
            }
            /* 跳过GEN_NULL */
            else
            {
                bytebuff_skip(p_st_data, 1);
                p_st_node = FRLIST_NEXT_NODE(p_st_node);
                continue;
            }
        }

        /* 解析Data = TYPE_VARBYTE */
        i_ret = sqlserver_skip_type_varbyte(p_st_data, i_whole_flg
                                           , p_st_metadata->i_data_type
                                           , p_st_metadata->ui_scale
                                           , p_st_metadata->ui_precision
                                           , p_st_metadata->i_mssql_plp_flg);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            return i_ret;
        }
        p_st_node = FRLIST_NEXT_NODE(p_st_node);
    }

    /* 设置出力参数 */
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析done token
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*           :  p_i_tds_ver(确切TDS版本号)
*           :  p_i_min_tds_ver(可能用的TDS最小版本号)
*           :  p_i_max_tds_ver(可能用的TDS最大版本号)
*           :  p_i_try_again_flg(该token是在未定义的情况下解析的，
*                             外围如果解析出错可能需要用高一级版本再解析一遍)
*           :  p_ull_effect_rows(影响到的数据库行数)
*  RTN      :  0       (normal)
*              1       (unknown)
*              2       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_done_token(Frbyte_Packet *p_st_data
                         , int i_whole_flg
                         , int *p_i_tds_ver
                         , int *p_i_min_tds_ver
                         , int *p_i_max_tds_ver
                         , int *p_i_try_again_flg
                         , int *p_i_normal_flg
                         , unsigned long long *p_ull_effect_rows)
{
    /* 定义
    * DONE = TokenType
    *        Status
    *        CurCmd
    *        DoneRowCount
    */
    int i_ret = FR_SUCC;
    uint8_t u8_tmp = 0;
    int i_done_flg = MSSQL_DONE_FINAL;
    unsigned int ui_done_row_count_len = 0;
    uint32_t u32_effect_rows = 0;
    uint64_t u64_effect_rows = 0;

    /* 说明：
    * 有协议可知 Status = USHORT (2byte),CurCmd = USHORT(2byte),
    * DoneRowCount = LONG(4byte)/ULONGLONG(8byte); (Changed to ULONGLONG in TDS 7.2)
    */

    /* 根据定义DONE token除了token type至少有2 + 2 + 4长度 */
    if (bytebuff_remaining(p_st_data) < 2 + 2 + 4)
    {
        goto error;
    }
    /* 取得DONE flag，确认是否是最后一个DONE token */
    bytebuff_peek_char(p_st_data, &u8_tmp);
    if (u8_tmp & 0x01)
    {
        i_done_flg = MSSQL_DONE_MORE;
    }
    /* 取得error flag */
    *p_i_normal_flg = FR_YES;
    if (u8_tmp & 0x02)
    {
        *p_i_normal_flg = FR_NO;
    }

    /* 跳过Status， CurCmd */
    bytebuff_skip(p_st_data, 2 + 2);

    /* 至少是7.2以上版本,DoneRowCount类型是ULONGLONG(8byte) */
    if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && *p_i_min_tds_ver >= MSSQL_TDS_VER_72)
         || (*p_i_tds_ver >= MSSQL_TDS_VER_72))
    {
        ui_done_row_count_len = 8;
        if (i_whole_flg == FR_YES)
        {
            /* 如果是最后一个done token，则剩余长度就应该等于DoneRowCount的长度 */
            if ((ui_done_row_count_len > (unsigned int)bytebuff_remaining(p_st_data))
               || (i_done_flg == MSSQL_DONE_FINAL
                   && ui_done_row_count_len != (unsigned int)bytebuff_remaining(p_st_data)))
            {
                return APM_L7_ANALYZE_FAIL;
            }
            i_ret = bytebuff_get_long(p_st_data, ui_done_row_count_len
                                     , &u64_effect_rows, BYTE_LITTLE_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            *p_ull_effect_rows = u64_effect_rows;
            return APM_L7_ANALYZE_SUCC;
        }
        else
        {
            if (ui_done_row_count_len > (unsigned int)bytebuff_remaining(p_st_data))
            {
                return APM_L7_ANALYZE_TODO;
            }
            else if (i_done_flg == MSSQL_DONE_FINAL
                     && ui_done_row_count_len != (unsigned int)bytebuff_remaining(p_st_data))
            {
                return APM_L7_ANALYZE_FAIL;
            }
            else
            {
                i_ret = bytebuff_get_long(p_st_data, ui_done_row_count_len
                                          , &u64_effect_rows, BYTE_LITTLE_ENDIAN);
                if (i_ret != FR_SUCC)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                *p_ull_effect_rows = u64_effect_rows;
                return APM_L7_ANALYZE_SUCC;
            }
        }
    }
    /* 至多是7.1R1版本,DoneRowCount类型是LONG(4byte) */
    else if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && *p_i_max_tds_ver < MSSQL_TDS_VER_72)
              || (*p_i_tds_ver != MSSQL_TDS_VER_NULL && *p_i_tds_ver < MSSQL_TDS_VER_72))
    {
        ui_done_row_count_len = 4;
        if (i_whole_flg == FR_YES)
        {
            /* 如果是最后一个done token，则剩余长度就应该等于DoneRowCount的长度 */
            if ((ui_done_row_count_len > (unsigned int)bytebuff_remaining(p_st_data))
               || (i_done_flg == MSSQL_DONE_FINAL
                   && ui_done_row_count_len != (unsigned int)bytebuff_remaining(p_st_data)))
            {
                return APM_L7_ANALYZE_FAIL;
            }
            i_ret = bytebuff_get_int(p_st_data, ui_done_row_count_len
                                     , &u32_effect_rows, BYTE_LITTLE_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            *p_ull_effect_rows = u32_effect_rows;
            return APM_L7_ANALYZE_SUCC;
        }
        else
        {
            if (ui_done_row_count_len > (unsigned int)bytebuff_remaining(p_st_data))
            {
                return APM_L7_ANALYZE_TODO;
            }
            else if (i_done_flg == MSSQL_DONE_FINAL
                     && ui_done_row_count_len != (unsigned int)bytebuff_remaining(p_st_data))
            {
                return APM_L7_ANALYZE_FAIL;
            }
            else
            {
                i_ret = bytebuff_get_int(p_st_data, ui_done_row_count_len
                                          , &u32_effect_rows, BYTE_LITTLE_ENDIAN);
                if (i_ret != FR_SUCC)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                *p_ull_effect_rows = u32_effect_rows;
                return APM_L7_ANALYZE_SUCC;
            }
        }
    }
    /* 版本不定 */
    else
    {
        /* 如果是最后一个done token，则根据长度可判定版本号 */
        if (i_done_flg == MSSQL_DONE_FINAL)
        {
            /* 等于4时表示TDS版本7.2以下的 */
            if (bytebuff_remaining(p_st_data) == 4)
            {
                ui_done_row_count_len = 4;
                *p_i_max_tds_ver = MSSQL_TDS_VER_71R1;
                /* 取得影响行数 */
                i_ret = bytebuff_get_int(p_st_data, ui_done_row_count_len
                                         , &u32_effect_rows, BYTE_LITTLE_ENDIAN);
                if (i_ret != FR_SUCC)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                *p_ull_effect_rows = u32_effect_rows;
                /* 确定TDS版本号 */
                if (*p_i_min_tds_ver == MSSQL_TDS_VER_71R1)
                {
                    *p_i_tds_ver = MSSQL_TDS_VER_71R1;
                }
                return APM_L7_ANALYZE_SUCC;
            }
            else if (bytebuff_remaining(p_st_data) == 8)
            {
                ui_done_row_count_len = 8;
                *p_i_min_tds_ver = MSSQL_TDS_VER_72;
                /* 取得影响行数 */
                i_ret = bytebuff_get_long(p_st_data, ui_done_row_count_len
                                         , &u64_effect_rows, BYTE_LITTLE_ENDIAN);
                if (i_ret != FR_SUCC)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                *p_ull_effect_rows = u64_effect_rows;
                /* 确定TDS版本号 */
                if (*p_i_max_tds_ver == MSSQL_TDS_VER_72)
                {
                    *p_i_tds_ver = MSSQL_TDS_VER_72;
                }
                return APM_L7_ANALYZE_SUCC;
            }
            /* 要用其他的版本再试试 */
            else
            {
                return APM_L7_ANALYZE_FAIL;
            }
        }
        /* 不是最后一个token，用版本较低的TDS先解析 */
        else
        {
            *p_i_try_again_flg = FR_YES;
            ui_done_row_count_len = 4;
            /* 取得影响行数 */
            i_ret = bytebuff_get_int(p_st_data, ui_done_row_count_len
                                     , &u32_effect_rows, BYTE_LITTLE_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            *p_ull_effect_rows = u32_effect_rows;
            *p_i_max_tds_ver = MSSQL_TDS_VER_71R1;
            if (*p_i_min_tds_ver == MSSQL_TDS_VER_71R1)
            {
                *p_i_tds_ver = MSSQL_TDS_VER_71R1;
            }
            return APM_L7_ANALYZE_SUCC;
        }
    }

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析doneinproc token
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*           :  p_i_tds_ver(确切TDS版本号)
*           :  p_i_min_tds_ver(可能用的TDS最小版本号)
*           :  p_i_max_tds_ver(可能用的TDS最大版本号)
*           :  p_i_try_again_flg(该token是在未定义的情况下解析的，
*                             外围如果解析出错可能需要用高一级版本再解析一遍)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_doneinproc_token(Frbyte_Packet *p_st_data
                               , int i_whole_flg
                               , int *p_i_tds_ver
                               , int *p_i_min_tds_ver
                               , int *p_i_max_tds_ver
                               , int *p_i_try_again_flg
                               , unsigned long long *p_ull_effect_rows)
{
    /* 注意：虽然与token定义相同，但是doneinproc token肯定不是最后一个token
    * DONE = TokenType
    *        Status
    *        CurCmd
    *        DoneRowCount
    */
    int i_ret = FR_SUCC;
    unsigned int ui_done_row_count_len = 0;
    uint32_t u32_effect_rows = 0;
    uint64_t u64_effect_rows = 0;

    /* 说明：
    * 有协议可知 Status = USHORT (2byte),CurCmd = USHORT(2byte),
    * DoneRowCount = LONG(4byte)/ULONGLONG(8byte); (Changed to ULONGLONG in TDS 7.2)
    */

    /* 根据定义DONE token除了token type至少有2 + 2 + 4长度 */
    if (bytebuff_remaining(p_st_data) <= 2 + 2 + 4)
    {
        goto error;
    }
    /* 跳过Status， CurCmd */
    bytebuff_skip(p_st_data, 2 + 2);

    /* 至少是7.2以上版本,DoneRowCount类型是ULONGLONG(8byte) */
    if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && *p_i_min_tds_ver >= MSSQL_TDS_VER_72)
         || (*p_i_tds_ver >= MSSQL_TDS_VER_72))
    {
        ui_done_row_count_len = 8;
        /* 如果是最后一个done token，则剩余长度就应该等于DoneRowCount的长度 */
        if (ui_done_row_count_len >= (unsigned int)bytebuff_remaining(p_st_data))
        {
            goto error;
        }
        i_ret = bytebuff_get_long(p_st_data, ui_done_row_count_len
                                 , &u64_effect_rows, BYTE_LITTLE_ENDIAN);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }

        *p_ull_effect_rows = u64_effect_rows;
        return APM_L7_ANALYZE_SUCC;
    }
    /* 至多是7.1R1版本,DoneRowCount类型是LONG(4byte) */
    else if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && *p_i_max_tds_ver < MSSQL_TDS_VER_72)
              || (*p_i_tds_ver != MSSQL_TDS_VER_NULL && *p_i_tds_ver < MSSQL_TDS_VER_72))
    {
        ui_done_row_count_len = 4;
        i_ret = bytebuff_get_int(p_st_data, ui_done_row_count_len
                                , &u32_effect_rows, BYTE_LITTLE_ENDIAN);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        *p_ull_effect_rows = u32_effect_rows;
        return APM_L7_ANALYZE_SUCC;
    }
    /* 版本不定 */
    else
    {
        /* 用版本较低的TDS先解析 */
        ui_done_row_count_len = 4;
        *p_i_try_again_flg = FR_YES;
        *p_i_max_tds_ver = MSSQL_TDS_VER_71R1;
        if (*p_i_min_tds_ver == MSSQL_TDS_VER_71R1)
        {
            *p_i_tds_ver = MSSQL_TDS_VER_71R1;
        }
        i_ret = bytebuff_get_int(p_st_data, ui_done_row_count_len
                                , &u32_effect_rows, BYTE_LITTLE_ENDIAN);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        *p_ull_effect_rows = u32_effect_rows;
        return APM_L7_ANALYZE_SUCC;
    }

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析doneproc token
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*           :  p_i_tds_ver(确切TDS版本号)
*           :  p_i_min_tds_ver(可能用的TDS最小版本号)
*           :  p_i_max_tds_ver(可能用的TDS最大版本号)
*           :  p_i_try_again_flg(该token是在未定义的情况下解析的，
*                             外围如果解析出错可能需要用高一级版本再解析一遍)
*           :  p_ull_effect_rows(影响到的数据库行数)
*  RTN      :  0       (normal)
*              1       (unknown)
*              2       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_doneproc_token(Frbyte_Packet *p_st_data
                             , int i_whole_flg
                             , int *p_i_tds_ver
                             , int *p_i_min_tds_ver
                             , int *p_i_max_tds_ver
                             , int *p_i_try_again_flg
                             , int *p_i_normal_flg
                             , unsigned long long *p_ull_effect_rows)
{
    /* 定义
    * DONEPROC = TokenType
    *        Status
    *        CurCmd
    *        DoneRowCount
    */
    int i_ret = FR_SUCC;
    uint8_t u8_tmp = 0;
    int i_done_flg = MSSQL_DONE_FINAL;
    unsigned int ui_done_row_count_len = 0;
    uint32_t u32_effect_rows = 0;
    uint64_t u64_effect_rows = 0;

    /* 说明：
    * 有协议可知 Status = USHORT (2byte),CurCmd = USHORT(2byte),
    * DoneRowCount = LONG(4byte)/ULONGLONG(8byte); (Changed to ULONGLONG in TDS 7.2)
    */

    /* 根据定义DONE token除了token type至少有2 + 2 + 4长度 */
    if (bytebuff_remaining(p_st_data) < 2 + 2 + 4)
    {
        goto error;
    }
    /* 取得DONE flag，确认是否是最后一个DONE token */
    bytebuff_peek_char(p_st_data, &u8_tmp);
    if (u8_tmp & 0x01)
    {
        i_done_flg = MSSQL_DONE_MORE;
    }
    /* 取得error flag */
    *p_i_normal_flg = FR_YES;
    if (u8_tmp & 0x02)
    {
        *p_i_normal_flg = FR_NO;
    }

    /* 跳过Status， CurCmd */
    bytebuff_skip(p_st_data, 2 + 2);

    /* 至少是7.2以上版本,DoneRowCount类型是ULONGLONG(8byte) */
    if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && *p_i_min_tds_ver >= MSSQL_TDS_VER_72)
         || (*p_i_tds_ver >= MSSQL_TDS_VER_72))
    {
        ui_done_row_count_len = 8;
        if (i_whole_flg == FR_YES)
        {
            /* 如果是最后一个done token，则剩余长度就应该等于DoneRowCount的长度 */
            if ((ui_done_row_count_len > (unsigned int)bytebuff_remaining(p_st_data))
               || (i_done_flg == MSSQL_DONE_FINAL
                   && ui_done_row_count_len != (unsigned int)bytebuff_remaining(p_st_data)))
            {
                return APM_L7_ANALYZE_FAIL;
            }
            i_ret = bytebuff_get_long(p_st_data, ui_done_row_count_len
                                     , &u64_effect_rows, BYTE_LITTLE_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            *p_ull_effect_rows = u64_effect_rows;
            return APM_L7_ANALYZE_SUCC;
        }
        else
        {
            if (ui_done_row_count_len > (unsigned int)bytebuff_remaining(p_st_data))
            {
                return APM_L7_ANALYZE_TODO;
            }
            else if (i_done_flg == MSSQL_DONE_FINAL
                     && ui_done_row_count_len != (unsigned int)bytebuff_remaining(p_st_data))
            {
                return APM_L7_ANALYZE_FAIL;
            }
            else
            {
                i_ret = bytebuff_get_long(p_st_data, ui_done_row_count_len
                                          , &u64_effect_rows, BYTE_LITTLE_ENDIAN);
                if (i_ret != FR_SUCC)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                *p_ull_effect_rows = u64_effect_rows;
                return APM_L7_ANALYZE_SUCC;
            }
        }
    }
    /* 至多是7.1R1版本,DoneRowCount类型是LONG(4byte) */
    else if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && *p_i_max_tds_ver < MSSQL_TDS_VER_72)
              || (*p_i_tds_ver != MSSQL_TDS_VER_NULL && *p_i_tds_ver < MSSQL_TDS_VER_72))
    {
        ui_done_row_count_len = 4;
        if (i_whole_flg == FR_YES)
        {
            /* 如果是最后一个done token，则剩余长度就应该等于DoneRowCount的长度 */
            if ((ui_done_row_count_len > (unsigned int)bytebuff_remaining(p_st_data))
               || (i_done_flg == MSSQL_DONE_FINAL
                   && ui_done_row_count_len != (unsigned int)bytebuff_remaining(p_st_data)))
            {
                return APM_L7_ANALYZE_FAIL;
            }
            i_ret = bytebuff_get_int(p_st_data, ui_done_row_count_len
                                     , &u32_effect_rows, BYTE_LITTLE_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            *p_ull_effect_rows = u32_effect_rows;
            return APM_L7_ANALYZE_SUCC;
        }
        else
        {
            if (ui_done_row_count_len > (unsigned int)bytebuff_remaining(p_st_data))
            {
                return APM_L7_ANALYZE_TODO;
            }
            else if (i_done_flg == MSSQL_DONE_FINAL
                     && ui_done_row_count_len != (unsigned int)bytebuff_remaining(p_st_data))
            {
                return APM_L7_ANALYZE_FAIL;
            }
            else
            {
                i_ret = bytebuff_get_int(p_st_data, ui_done_row_count_len
                                          , &u32_effect_rows, BYTE_LITTLE_ENDIAN);
                if (i_ret != FR_SUCC)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                *p_ull_effect_rows = u32_effect_rows;
                return APM_L7_ANALYZE_SUCC;
            }
        }
    }
    /* 版本不定 */
    else
    {
        /* 如果是最后一个done token，则根据长度可判定版本号 */
        if (i_done_flg == MSSQL_DONE_FINAL)
        {
            /* 等于4时表示TDS版本7.2以下的 */
            if (bytebuff_remaining(p_st_data) == 4)
            {
                ui_done_row_count_len = 4;
                *p_i_max_tds_ver = MSSQL_TDS_VER_71R1;
                /* 取得影响行数 */
                i_ret = bytebuff_get_int(p_st_data, ui_done_row_count_len
                                         , &u32_effect_rows, BYTE_LITTLE_ENDIAN);
                if (i_ret != FR_SUCC)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                *p_ull_effect_rows = u32_effect_rows;
                /* 确定TDS版本号 */
                if (*p_i_min_tds_ver == MSSQL_TDS_VER_71R1)
                {
                    *p_i_tds_ver = MSSQL_TDS_VER_71R1;
                }
                return APM_L7_ANALYZE_SUCC;
            }
            else if (bytebuff_remaining(p_st_data) == 8)
            {
                ui_done_row_count_len = 8;
                *p_i_min_tds_ver = MSSQL_TDS_VER_72;
                /* 取得影响行数 */
                i_ret = bytebuff_get_long(p_st_data, ui_done_row_count_len
                                         , &u64_effect_rows, BYTE_LITTLE_ENDIAN);
                if (i_ret != FR_SUCC)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                *p_ull_effect_rows = u64_effect_rows;
                /* 确定TDS版本号 */
                if (*p_i_max_tds_ver == MSSQL_TDS_VER_72)
                {
                    *p_i_tds_ver = MSSQL_TDS_VER_72;
                }
                return APM_L7_ANALYZE_SUCC;
            }
            /* 要用其他的版本再试试 */
            else
            {
                return APM_L7_ANALYZE_FAIL;
            }
        }
        /* 不是最后一个token，用版本较低的TDS先解析 */
        else
        {
            *p_i_try_again_flg = FR_YES;
            ui_done_row_count_len = 4;
            /* 取得影响行数 */
            i_ret = bytebuff_get_int(p_st_data, ui_done_row_count_len
                                     , &u32_effect_rows, BYTE_LITTLE_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            *p_ull_effect_rows = u32_effect_rows;
            *p_i_max_tds_ver = MSSQL_TDS_VER_71R1;
            if (*p_i_min_tds_ver == MSSQL_TDS_VER_71R1)
            {
                *p_i_tds_ver = MSSQL_TDS_VER_71R1;
            }
            return APM_L7_ANALYZE_SUCC;
        }
    }

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析envchange token
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*           :  p_i_tds_ver(确切TDS版本号)
*           :  p_i_min_tds_ver(可能用的TDS最小版本号)
*           :  p_i_max_tds_ver(可能用的TDS最大版本号)
*           :  pp_charset(协议charset)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_envchange_token(Frbyte_Packet *p_st_data
                              , int i_whole_flg
                              , int *p_i_tds_ver
                              , int *p_i_min_tds_ver
                              , int *p_i_max_tds_ver
                              , char **pp_charset)
{
    /* 定义
    *  ENVCHANGE = TokenType
    *              Length
    *              EnvValueData
    *  EnvValueData = Type
    *                 NewValue
    *                 [OldValue]
    */

    int i_ret = FR_SUCC;
    uint16_t u16_token_len = 0;
    uint8_t u8_env_type = 0;
    uint8_t u8_tmp = 0;
    unsigned int ui_value_len = 0;
    uint16_t u16_routing_len = 0;
    unsigned int ui_position1 = 0;
    unsigned int ui_position2 = 0;
    unsigned int ui_position3 = 0;
    char *p_value = NULL;
    char arr_tmp[2] ={0};

    /* 取得env token长度 */
    if (bytebuff_remaining(p_st_data) <  MSSQL_TDS_USHORT_LEN)
    {
        goto error;
    }
    i_ret = bytebuff_get_short(p_st_data, MSSQL_TDS_USHORT_LEN
                              , &u16_token_len, BYTE_LITTLE_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 长度判断 */
    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto error;
    }

    bytebuff_get_char(p_st_data, &u8_env_type);
    u16_token_len--;
    ui_position1 = bytebuff_getPosition(p_st_data);
    /* 根据env type解析数据 */
    switch (u8_env_type)
    {
        case MSSQL_ENV_TYPE_DATABASE:
        case MSSQL_ENV_TYPE_LANGUAGE:
        case MSSQL_ENV_TYPE_PACKET:
            /* 跳过NewValue */
            i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg
                                         , APM_TDS_B_VARCHAR, FR_NO
                                         , &p_value, &ui_value_len);
            if (i_ret == APM_L7_ANALYZE_FAIL)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            else if (i_ret == APM_L7_ANALYZE_TODO)
            {
                ui_position2 = bytebuff_getPosition(p_st_data);
                if (u16_token_len < ui_position2 - ui_position1)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                else
                {
                    return APM_L7_ANALYZE_TODO;
                }
            }

            ui_position2 = bytebuff_getPosition(p_st_data);
            if (u16_token_len < ui_position2 - ui_position1)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            u16_token_len -= ui_position2 - ui_position1;
            /* 还有oldvalue需要跳过 */
            if (u16_token_len)
            {
                i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg
                                              , APM_TDS_B_VARCHAR, FR_NO
                                              , &p_value, &ui_value_len);
                if (i_ret == APM_L7_ANALYZE_FAIL)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                else if (i_ret == APM_L7_ANALYZE_TODO)
                {
                    ui_position3 = bytebuff_getPosition(p_st_data);
                    if (u16_token_len < ui_position3 - ui_position2)
                    {
                        return APM_L7_ANALYZE_FAIL;
                    }
                    else
                    {
                        return APM_L7_ANALYZE_TODO;
                    }
                }

                ui_position3 = bytebuff_getPosition(p_st_data);
                if (u16_token_len != ui_position3 - ui_position2)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
            }
            break;

        /* 需要将Charset取出 */
        case MSSQL_ENV_TYPE_CHARSET:
            /* 取得Charset的NewValue */
            i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg
                                         , APM_TDS_B_VARCHAR, FR_YES
                                         , pp_charset, &ui_value_len);
            if (i_ret == APM_L7_ANALYZE_FAIL)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            else if (i_ret == APM_L7_ANALYZE_TODO)
            {
                ui_position2 = bytebuff_getPosition(p_st_data);
                if (u16_token_len < ui_position2 - ui_position1)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                else
                {
                    return APM_L7_ANALYZE_TODO;
                }
            }

            ui_position2 = bytebuff_getPosition(p_st_data);
            if (u16_token_len < ui_position2 - ui_position1)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            u16_token_len -= ui_position2 - ui_position1;
            /* 还有oldvalue需要跳过 */
            if (u16_token_len)
            {
                i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg
                                              , APM_TDS_B_VARCHAR, FR_NO
                                              , &p_value, &ui_value_len);
                if (i_ret == APM_L7_ANALYZE_FAIL)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                else if (i_ret == APM_L7_ANALYZE_TODO)
                {
                    ui_position3 = bytebuff_getPosition(p_st_data);
                    if (u16_token_len < ui_position3 - ui_position2)
                    {
                        return APM_L7_ANALYZE_FAIL;
                    }
                    else
                    {
                        return APM_L7_ANALYZE_TODO;
                    }
                }

                ui_position3 = bytebuff_getPosition(p_st_data);
                if (u16_token_len != ui_position3 - ui_position2)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
            }
            break;

        case MSSQL_ENV_TYPE_UCS2ID:
        case MSSQL_ENV_TYPE_UCS2FLG:
            /* 跳过NewValue */
            i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg
                                         , APM_TDS_B_VARCHAR, FR_NO
                                         , &p_value, &ui_value_len);
            if (i_ret == APM_L7_ANALYZE_FAIL)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            else if (i_ret == APM_L7_ANALYZE_TODO)
            {
                ui_position2 = bytebuff_getPosition(p_st_data);
                if (u16_token_len < ui_position2 - ui_position1)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                else
                {
                    return APM_L7_ANALYZE_TODO;
                }
            }

            ui_position2 = bytebuff_getPosition(p_st_data);
            if (u16_token_len <= ui_position2 - ui_position1)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            u16_token_len -= ui_position2 - ui_position1;
            bytebuff_get_char(p_st_data, &u8_tmp);
            /* old value是0x00 */
            if (u16_token_len != 1 || u8_tmp != '\0')
            {
                return APM_L7_ANALYZE_FAIL;
            }
            break;

        case MSSQL_ENV_TYPE_SQL:
            /* 跳过NewValue */
            i_ret = sqlserver_get_varbytes(p_st_data, i_whole_flg
                                           , APM_TDS_B_VARBYTE, FR_NO
                                           , &p_value, &ui_value_len);
            if (i_ret == APM_L7_ANALYZE_FAIL)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            else if (i_ret == APM_L7_ANALYZE_TODO)
            {
                ui_position2 = bytebuff_getPosition(p_st_data);
                if (u16_token_len < ui_position2 - ui_position1)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                else
                {
                    return APM_L7_ANALYZE_TODO;
                }
            }

            ui_position2 = bytebuff_getPosition(p_st_data);
            if (u16_token_len < ui_position2 - ui_position1)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            u16_token_len -= ui_position2 - ui_position1;
            /* 还有oldvalue需要跳过 */
            if (u16_token_len)
            {
                i_ret = sqlserver_get_varbytes(p_st_data, i_whole_flg
                                               , APM_TDS_B_VARBYTE, FR_NO
                                               , &p_value, &ui_value_len);
                if (i_ret == APM_L7_ANALYZE_FAIL)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                else if (i_ret == APM_L7_ANALYZE_TODO)
                {
                    ui_position3 = bytebuff_getPosition(p_st_data);
                    if (u16_token_len < ui_position3 - ui_position2)
                    {
                        return APM_L7_ANALYZE_FAIL;
                    }
                    else
                    {
                        return APM_L7_ANALYZE_TODO;
                    }
                }

                ui_position3 = bytebuff_getPosition(p_st_data);
                if (u16_token_len != ui_position3 - ui_position2)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
            }
            break;

        /* Types 8(begin transaction) to 19(back name) were introduced in TDS 7.2 */
        case MSSQL_ENV_TYPE_BGEINTRANS:
        case MSSQL_ENV_TYPE_DEFECTTRANS:
        case MSSQL_ENV_TYPE_TRANSADDR:
            /* 跳过NewValue */
            i_ret = sqlserver_get_varbytes(p_st_data, i_whole_flg
                                           , APM_TDS_B_VARBYTE, FR_NO
                                           , &p_value, &ui_value_len);
            if (i_ret == APM_L7_ANALYZE_FAIL)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            else if (i_ret == APM_L7_ANALYZE_TODO)
            {
                ui_position2 = bytebuff_getPosition(p_st_data);
                if (u16_token_len < ui_position2 - ui_position1)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                else
                {
                    return APM_L7_ANALYZE_TODO;
                }
            }

            ui_position2 = bytebuff_getPosition(p_st_data);
            if (u16_token_len <= ui_position2 - ui_position1)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            u16_token_len -= ui_position2 - ui_position1;
            bytebuff_get_char(p_st_data, &u8_tmp);
            /* old value是0x00 */
            if (u16_token_len != 1 || u8_tmp != '\0')
            {
                return APM_L7_ANALYZE_FAIL;
            }
            /* 设置版本号 */
            if (*p_i_max_tds_ver < MSSQL_TDS_VER_72)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            if (*p_i_min_tds_ver < MSSQL_TDS_VER_72)
            {
                *p_i_min_tds_ver = MSSQL_TDS_VER_72;
                if (*p_i_max_tds_ver == MSSQL_TDS_VER_72)
                {
                    *p_i_tds_ver = MSSQL_TDS_VER_72;
                }
            }
            break;

        case MSSQL_ENV_TYPE_COMMITTRANS:
        case MSSQL_ENV_TYPE_ROLLBACKTRANS:
        case MSSQL_ENV_TYPE_DTCTRANS:
        case MSSQL_ENV_TYPE_TRANSEND:
        case MSSQL_ENV_TYPE_NAME:
            if (u16_token_len < 1)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            /* 跳过newvalue 0x00 */
            bytebuff_get_char(p_st_data, &u8_tmp);
            if (u8_tmp != '\0')
            {
                return APM_L7_ANALYZE_FAIL;
            }
            /* 跳过oldvalue */
            i_ret = sqlserver_get_varbytes(p_st_data, i_whole_flg
                                           , APM_TDS_B_VARBYTE, FR_NO
                                           , &p_value, &ui_value_len);
            if (i_ret == APM_L7_ANALYZE_FAIL)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            else if (i_ret == APM_L7_ANALYZE_TODO)
            {
                ui_position2 = bytebuff_getPosition(p_st_data);
                if (u16_token_len < ui_position2 - ui_position1)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                else
                {
                    return APM_L7_ANALYZE_TODO;
                }
            }

            ui_position2 = bytebuff_getPosition(p_st_data);
            if (u16_token_len != ui_position2 - ui_position1)
            {
                return APM_L7_ANALYZE_FAIL;
            }

            /* 设置版本号 */
            if (*p_i_max_tds_ver < MSSQL_TDS_VER_72)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            if (*p_i_min_tds_ver < MSSQL_TDS_VER_72)
            {
                *p_i_min_tds_ver = MSSQL_TDS_VER_72;
                if (*p_i_max_tds_ver == MSSQL_TDS_VER_72)
                {
                    *p_i_tds_ver = MSSQL_TDS_VER_72;
                }
            }
            break;

        case MSSQL_ENV_TYPE_LOG:
            /* 跳过NewValue */
            i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg
                                         , APM_TDS_B_VARCHAR, FR_NO
                                         , &p_value, &ui_value_len);
            if (i_ret == APM_L7_ANALYZE_FAIL)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            else if (i_ret == APM_L7_ANALYZE_TODO)
            {
                ui_position2 = bytebuff_getPosition(p_st_data);
                if (u16_token_len < ui_position2 - ui_position1)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                else
                {
                    return APM_L7_ANALYZE_TODO;
                }
            }

            ui_position2 = bytebuff_getPosition(p_st_data);
            if (u16_token_len <= ui_position2 - ui_position1)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            u16_token_len -= ui_position2 - ui_position1;
            bytebuff_get_char(p_st_data, &u8_tmp);
            /* old value是0x00 */
            if (u16_token_len != 1 || u8_tmp != '\0')
            {
                return APM_L7_ANALYZE_FAIL;
            }

            /* 设置版本号 */
            if (*p_i_max_tds_ver < MSSQL_TDS_VER_72)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            if (*p_i_min_tds_ver < MSSQL_TDS_VER_72)
            {
                *p_i_min_tds_ver = MSSQL_TDS_VER_72;
                if (*p_i_max_tds_ver == MSSQL_TDS_VER_72)
                {
                    *p_i_tds_ver = MSSQL_TDS_VER_72;
                }
            }
            break;

        case MSSQL_ENV_TYPE_PROMOTETRANS:
            /* 跳过NEWvalue */
            i_ret = sqlserver_get_varbytes(p_st_data, i_whole_flg
                                           , APM_TDS_L_VARBYTE, FR_NO
                                           , &p_value, &ui_value_len);
            if (i_ret == APM_L7_ANALYZE_FAIL)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            else if (i_ret == APM_L7_ANALYZE_TODO)
            {
                ui_position2 = bytebuff_getPosition(p_st_data);
                if (u16_token_len < ui_position2 - ui_position1)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                else
                {
                    return APM_L7_ANALYZE_TODO;
                }
            }

            ui_position2 = bytebuff_getPosition(p_st_data);
            if (u16_token_len <= ui_position2 - ui_position1)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            u16_token_len -= ui_position2 - ui_position1;
            bytebuff_get_char(p_st_data, &u8_tmp);
            /* old value是0x00 */
            if (u16_token_len != 1 || u8_tmp != '\0')
            {
                return APM_L7_ANALYZE_FAIL;
            }

            /* 设置版本号 */
            if (*p_i_max_tds_ver < MSSQL_TDS_VER_72)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            if (*p_i_min_tds_ver < MSSQL_TDS_VER_72)
            {
                *p_i_min_tds_ver = MSSQL_TDS_VER_72;
                if (*p_i_max_tds_ver == MSSQL_TDS_VER_72)
                {
                    *p_i_tds_ver = MSSQL_TDS_VER_72;
                }
            }
            break;

        case MSSQL_ENV_TYPE_ACKNOWLEDGEMENT:
            /* oldvalue和newvalue都是0x00 */
            if (u16_token_len != 2)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            i_ret = bytebuff_get_bytes(p_st_data, arr_tmp, 2);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }

            if (arr_tmp[0] != '\0' || arr_tmp[1] != '\0')
            {
                return APM_L7_ANALYZE_FAIL;
            }

            /* 设置版本号 */
            if (*p_i_max_tds_ver < MSSQL_TDS_VER_72)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            if (*p_i_min_tds_ver < MSSQL_TDS_VER_72)
            {
                *p_i_min_tds_ver = MSSQL_TDS_VER_72;
                if (*p_i_max_tds_ver == MSSQL_TDS_VER_72)
                {
                    *p_i_tds_ver = MSSQL_TDS_VER_72;
                }
            }
            break;

        /* Type 20(routing) was introduced in TDS 7.4 */
        case MSSQL_ENV_TYPE_ROUTING:
            if (u16_token_len < 2)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            /* 取得routing value length */
            i_ret = bytebuff_get_short(p_st_data, MSSQL_TDS_USHORT_LEN
                                      , &u16_routing_len, BYTE_LITTLE_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }

            if (u16_token_len != 2 + u16_routing_len)
            {
                return APM_L7_ANALYZE_FAIL;
            }

            bytebuff_skip(p_st_data, u16_routing_len);
            u16_token_len -= 2 + u16_routing_len;

            /* 设置版本号 */
            if (*p_i_max_tds_ver < MSSQL_TDS_VER_74)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            if (*p_i_min_tds_ver < MSSQL_TDS_VER_74)
            {
                *p_i_min_tds_ver = MSSQL_TDS_VER_74;
                if (*p_i_max_tds_ver == MSSQL_TDS_VER_74)
                {
                    *p_i_tds_ver = MSSQL_TDS_VER_74;
                }
            }
            break;

        default:
            return APM_L7_ANALYZE_FAIL;
    }

    /* 设置出力 */
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析error token
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*           :  p_i_tds_ver(确切TDS版本号)
*           :  p_i_min_tds_ver(可能用的TDS最小版本号)
*           :  p_i_max_tds_ver(可能用的TDS最大版本号)
*           :  p_ll_error_num(error number)
*           :  pp_error_msg(error message)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_error_token(Frbyte_Packet *p_st_data
                          , int i_whole_flg
                          , int *p_i_tds_ver
                          , int *p_i_min_tds_ver
                          , int *p_i_max_tds_ver
                          , long long *p_ll_error_num
                          , char **pp_error_msg)
{
    /* 定义：
    * ERROR = TokenType
    *           Length
    *           Number
    *           State
    *           Class
    *           MsgText
    *           ServerName
    *           ProcName
    *           LineNumber
    */

    int i_ret = FR_SUCC;
    uint16_t u16_token_len = 0;
    uint32_t u32_token_len = 0;
    int i_error_num = 0;
    unsigned int ui_msg_len = 0;
    unsigned int ui_position1 = 0;
    unsigned int ui_position2 = 0;
    unsigned int ui_errmsg_len = 0;
    char *p_value = NULL;
    char *p_error_msg = NULL;
    char *p_error_msg_pre = NULL;

    /*  取得整个token的长度 */
    if (bytebuff_remaining(p_st_data) < MSSQL_TDS_USHORT_LEN)
    {
        goto error;
    }
    i_ret = bytebuff_get_short(p_st_data, MSSQL_TDS_USHORT_LEN
                              , &u16_token_len, BYTE_LITTLE_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 取得error number */
    if (u16_token_len < 4)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    i_ret = bytebuff_get_int(p_st_data, 4
                             , &u32_token_len, BYTE_LITTLE_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    i_error_num = (int)u32_token_len;
    u16_token_len -= 4;

    /* 跳过state，class */
    if (u16_token_len < 1 + 1)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    bytebuff_skip(p_st_data, 2);
    u16_token_len -= 2;

    ui_position1 = bytebuff_getPosition(p_st_data);
    /* 取得error message text */
    i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg
                                 , APM_TDS_US_VARCHAR, FR_YES
                                 , &p_error_msg, &ui_msg_len);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }

    /* 跳过server name */
    i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg
                                 , APM_TDS_B_VARCHAR, FR_NO
                                 , &p_value, &ui_msg_len);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        sqlserver_free((void **)&p_error_msg);
        return i_ret;
    }
    /* 跳过process name */
    i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg
                                 , APM_TDS_B_VARCHAR, FR_NO
                                 , &p_value, &ui_msg_len);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        sqlserver_free((void **)&p_error_msg);
        return i_ret;
    }

    ui_position2 = bytebuff_getPosition(p_st_data);
    if (ui_position2 - ui_position1 > u16_token_len)
    {
        sqlserver_free((void **)&p_error_msg);
        return APM_L7_ANALYZE_FAIL;
    }
    u16_token_len -= ui_position2 - ui_position1;

    /* 根据剩余长度判断版本 */
    if (u16_token_len == MSSQL_TDS_USHORT_LEN)
    {
        bytebuff_skip(p_st_data, MSSQL_TDS_USHORT_LEN);
        if (*p_i_tds_ver == MSSQL_TDS_VER_NULL)
        {
            if (*p_i_min_tds_ver >= MSSQL_TDS_VER_72)
            {
                sqlserver_free((void **)&p_error_msg);
                return APM_L7_ANALYZE_FAIL;
            }
            else if (*p_i_min_tds_ver == MSSQL_TDS_VER_71R1)
            {
                *p_i_tds_ver = MSSQL_TDS_VER_71R1;
            }
            *p_i_max_tds_ver = MSSQL_TDS_VER_71R1;
        }
        else if (*p_i_tds_ver >= MSSQL_TDS_VER_72)
        {
            sqlserver_free((void **)&p_error_msg);
            return APM_L7_ANALYZE_FAIL;
        }
    }
    else if (u16_token_len == MSSQL_TDS_ULONG_LEN)
    {
        bytebuff_skip(p_st_data, MSSQL_TDS_ULONG_LEN);
        /* 设置版本号 */
        if (*p_i_tds_ver == MSSQL_TDS_VER_NULL)
        {
            if (*p_i_max_tds_ver < MSSQL_TDS_VER_72)
            {
                sqlserver_free((void **)&p_error_msg);
                return APM_L7_ANALYZE_FAIL;
            }
            else if (*p_i_max_tds_ver == MSSQL_TDS_VER_72)
            {
                *p_i_tds_ver = MSSQL_TDS_VER_72;
            }
            *p_i_min_tds_ver = MSSQL_TDS_VER_72;
        }
        else if (*p_i_tds_ver < MSSQL_TDS_VER_72)
        {
            sqlserver_free((void **)&p_error_msg);
            return APM_L7_ANALYZE_FAIL;
        }
    }
    else
    {
        sqlserver_free((void **)&p_error_msg);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 设置出力 */
    *p_ll_error_num = i_error_num;
    if (*pp_error_msg == NULL)
    {
        *pp_error_msg = p_error_msg;
    }
    else
    {
        p_error_msg_pre = *pp_error_msg;
        ui_errmsg_len = strlen(p_error_msg_pre) + 1 + strlen(p_error_msg) + 1;
        *pp_error_msg = (char *)frmalloc(ui_errmsg_len);
        if (*pp_error_msg == NULL)
        {
            frfree(p_error_msg);
            frfree(p_error_msg_pre);
            return APM_L7_ANALYZE_FAIL;
        }
        else
        {
            snprintf(*pp_error_msg, ui_errmsg_len, "%s\n%s", p_error_msg_pre, p_error_msg);
            frfree(p_error_msg);
            frfree(p_error_msg_pre);
        }
    }
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析featureextack token
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_featureextack_token(Frbyte_Packet *p_st_data, int i_whole_flg)
{
    /*
    * FEATUREEXTACK = TokenType
    *                 1*FeatureAckOpt
    * FeatureAckOpt = (FeatureId
    *                  FeatureAckDataLen
    *                  FeatureAckData)
    *                  /
    *                  TERMINATOR
    */
    int i_ret = FR_SUCC;
    uint8_t u8_id = 0;
    uint32_t u32_date_len = 0;

    /* 至少有一个FeatureAckOpt */
    if (bytebuff_remaining(p_st_data) == 0)
    {
        goto error;
    }

    while (bytebuff_remaining(p_st_data))
    {
        /* 取得FeatureId */
        bytebuff_get_char(p_st_data, &u8_id);
        /* featureextack token的结束ID */
        if (u8_id == 0xFF)
        {
            break;
        }

        /* 取得FeatureAckDataLen */
        if (bytebuff_remaining(p_st_data) < MSSQL_TDS_DWORD_LEN)
        {
            goto error;
        }
        i_ret = bytebuff_get_int(p_st_data, MSSQL_TDS_DWORD_LEN
                                 , &u32_date_len, BYTE_LITTLE_ENDIAN);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }

        /* 跳过FeatureAckData */
        if (u32_date_len > (unsigned int)bytebuff_remaining(p_st_data))
        {
            goto error;
        }
        bytebuff_skip(p_st_data, u32_date_len);
    }

    /* 设置出力 */
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*           :  p_i_tds_ver(确切TDS版本号)
*           :  p_i_min_tds_ver(可能用的TDS最小版本号)
*           :  p_i_max_tds_ver(可能用的TDS最大版本号)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_info_token(Frbyte_Packet *p_st_data
                         , int i_whole_flg
                         , int *p_i_tds_ver
                         , int *p_i_min_tds_ver
                         , int *p_i_max_tds_ver)
{
    /* 定义：
    * INFO = TokenType
    *           Length
    *           Number
    *           State
    *           Class
    *           MsgText
    *           ServerName
    *           ProcName
    *           LineNumber
    */

    int i_ret = FR_SUCC;
    uint16_t u16_token_len = 0;
    unsigned int ui_msg_len = 0;
    unsigned int ui_position1 = 0;
    unsigned int ui_position2 = 0;
    char *p_value = NULL;

    /*  取得整个token的长度 */
    if (bytebuff_remaining(p_st_data) < MSSQL_TDS_USHORT_LEN)
    {
        goto error;
    }
    i_ret = bytebuff_get_short(p_st_data, MSSQL_TDS_USHORT_LEN
                              , &u16_token_len, BYTE_LITTLE_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto error;
    }

    /* 跳过number，state，class */
    if (u16_token_len < MSSQL_TDS_LONG_LEN + MSSQL_TDS_BYTE_LEN + MSSQL_TDS_BYTE_LEN)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    bytebuff_skip(p_st_data, MSSQL_TDS_LONG_LEN + MSSQL_TDS_BYTE_LEN + MSSQL_TDS_BYTE_LEN);
    u16_token_len -= MSSQL_TDS_LONG_LEN + MSSQL_TDS_BYTE_LEN + MSSQL_TDS_BYTE_LEN;

    ui_position1 = bytebuff_getPosition(p_st_data);

    /* 跳过 message text */
    i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg
                                 , APM_TDS_US_VARCHAR, FR_NO
                                 , &p_value, &ui_msg_len);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }

    /* 跳过server name */
    i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg
                                 , APM_TDS_B_VARCHAR, FR_NO
                                 , &p_value, &ui_msg_len);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }
    /* 跳过process name */
    i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg
                                 , APM_TDS_B_VARCHAR, FR_NO
                                 , &p_value, &ui_msg_len);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }
    ui_position2 = bytebuff_getPosition(p_st_data);
    if (ui_position2 - ui_position1 > u16_token_len)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    u16_token_len -= ui_position2 - ui_position1;
    /* 根据剩余长度判断版本 */
    if (u16_token_len == MSSQL_TDS_USHORT_LEN)
    {
        bytebuff_skip(p_st_data, MSSQL_TDS_USHORT_LEN);
        if (*p_i_tds_ver == MSSQL_TDS_VER_NULL)
        {
            if (*p_i_min_tds_ver >= MSSQL_TDS_VER_72)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            else if (*p_i_min_tds_ver == MSSQL_TDS_VER_71R1)
            {
                *p_i_tds_ver = MSSQL_TDS_VER_71R1;
            }
            *p_i_max_tds_ver = MSSQL_TDS_VER_71R1;
        }
        else if (*p_i_tds_ver >= MSSQL_TDS_VER_72)
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }
    else if (u16_token_len == MSSQL_TDS_ULONG_LEN)
    {
        bytebuff_skip(p_st_data, MSSQL_TDS_ULONG_LEN);
        /* 设置版本号 */
        if (*p_i_tds_ver == MSSQL_TDS_VER_NULL)
        {
            if (*p_i_max_tds_ver < MSSQL_TDS_VER_72)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            else if (*p_i_max_tds_ver == MSSQL_TDS_VER_72)
            {
                *p_i_tds_ver = MSSQL_TDS_VER_72;
            }
            *p_i_min_tds_ver = MSSQL_TDS_VER_72;
        }
        else if (*p_i_tds_ver < MSSQL_TDS_VER_72)
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }
    else
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 设置出力 */
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析 loginack token
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*           :  p_i_ser_tds_ver(服务端TDS版本号)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_loginack_token(Frbyte_Packet *p_st_data
                             , int i_whole_flg
                             , int *p_i_ser_tds_ver)
{
    /*
    * LOGINACK = TokenType
    *            Length
    *            Interface
    *            TDSVersion
    *            ProgName
    *            ProgVersion
    * ProgVersion = MajorVer
    *               MinorVer
    *               BuildNumHi
    *               BuildNumLow
    */
    int i_ret = FR_SUCC;
    int i_tds_ver = 0;
    uint16_t u16_token_len = 0;
    unsigned int ui_value_len = 0;
    unsigned int ui_position1 = 0;
    unsigned int ui_position2 = 0;
    char *p_value = NULL;

    /* 取得token长度 */
    if (bytebuff_remaining(p_st_data) < MSSQL_TDS_USHORT_LEN)
    {
        goto error;
    }
    i_ret = bytebuff_get_short(p_st_data, MSSQL_TDS_USHORT_LEN
                              , &u16_token_len, BYTE_LITTLE_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
         goto error;
    }

    /* 跳过Interface */
    if (u16_token_len < MSSQL_TDS_BYTE_LEN)
    {
         return APM_L7_ANALYZE_FAIL;
    }
    bytebuff_skip(p_st_data, MSSQL_TDS_BYTE_LEN);
    u16_token_len -= MSSQL_TDS_BYTE_LEN;

    ui_position1 = bytebuff_getPosition(p_st_data);
    /* 取得客户端TDS version */
    i_ret = sqlserver_tds_ver_get(p_st_data, MSSQL_SRV2CLI, &i_tds_ver);
    /* LOGIN7结构格式不正 */
    if (i_ret == FR_FAIL)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 跳过ProgName */
    i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg
                                  , APM_TDS_B_VARCHAR, FR_NO
                                  , &p_value, &ui_value_len);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }

    ui_position2 = bytebuff_getPosition(p_st_data);
    if (ui_position2 - ui_position1 > u16_token_len)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 跳过ProgVersion */
    u16_token_len -= ui_position2 - ui_position1;
    if (u16_token_len != MSSQL_TDS_DWORD_LEN)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    bytebuff_skip(p_st_data, MSSQL_TDS_DWORD_LEN);

    *p_i_ser_tds_ver = i_tds_ver;
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*           :  p_i_tds_ver(确切TDS版本号)
*           :  p_i_min_tds_ver(可能用的TDS最小版本号)
*           :  p_i_max_tds_ver(可能用的TDS最大版本号)
*           :  p_st_altmetadata_info(altmetadata结构体)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_nbcrow_token(Frbyte_Packet *p_st_data
                           , int i_whole_flg
                           , int *p_i_tds_ver
                           , int *p_i_min_tds_ver
                           , int *p_i_max_tds_ver
                           , Frlist_header *p_lst_colmetadata)
{
    /*定义：
    * NBCROW = TokenType
    *          NullBitmap
    *          AllColumnData
    * TokenType = BYTE
    * TextPointer = B_VARBYTE
    * Timestamp = 8BYTE
    * Data = TYPE_VARBYTE
    * NullBitmap = <NullBitmapByteCount>BYTE;
    * ColumnData = [TextPointer Timestamp] Data
    * AllColumnData = *ColumnData
    */
    unsigned int ui_position = 0;
    int i_index = 0;
    int i_ret = FR_SUCC;
    uint8_t u8_byte = 0;
    uint8_t u8_text = 0;
    int i_data_type = 0;
    unsigned int ui_loop = 0;
    unsigned int ui_value_len = 0;
    unsigned int ui_row_count = frlist_size(p_lst_colmetadata);
    unsigned int ui_null_bitmap_byte_count = 0;
    char *p_value = NULL;
    char arr_compressed_null[ui_row_count];
    Frlist_node *p_st_node = NULL;
    Sql_metadata_info *p_st_metadata = NULL;

    /* NBCROW token是TDS 7.3版本里新加进来的 */
    if (*p_i_tds_ver == MSSQL_TDS_VER_NULL)
    {
        if (*p_i_max_tds_ver < MSSQL_TDS_VER_73)
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }
    else if (*p_i_tds_ver < MSSQL_TDS_VER_73)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 解析<NullBitmapByteCount>BYTE，取得压缩信息 */
    /* 1.
    * 根据协议：NullBitmapByteCount is equal to the smallest number of bytes
    * needed to hold the number of columns in COLMETADATA.
    */
    ui_null_bitmap_byte_count = ((ui_row_count - 1) >> 3) + 1;
    if (ui_null_bitmap_byte_count > (unsigned int)bytebuff_remaining(p_st_data))
    {
        goto error;
    }

    /* 2.根据官方驱动取得NULL字段的位置 */
    memset(arr_compressed_null, 0x00, sizeof(arr_compressed_null));
    for (ui_loop = 0; ui_loop < ui_null_bitmap_byte_count; ui_loop++)
    {
        bytebuff_get_char(p_st_data, &u8_byte);

        if (u8_byte == 0)
        {
            ui_position += 8;
        }
        else
        {
            for (i_index = 0; ((i_index < 8) && (ui_position < ui_row_count)); i_index++)
            {
                if ((u8_byte & (1 << i_index)) != 0)
                {
                    arr_compressed_null[ui_position] = 1;
                }
                ui_position++;
            }
        }
    }

    ui_loop = 0;
    p_st_node = FRLIST_FIRST_NODE(p_lst_colmetadata);
    /* 解析AllColumnData */
    while (p_st_node)
    {
        p_st_metadata = (Sql_metadata_info *)FRLIST_GET_NODE_DATA(p_st_node);
        i_data_type = p_st_metadata->i_data_type;
        /* 只有未被压缩的字段才需要去解析 */
        if (arr_compressed_null[ui_loop] == 0)
        {
            /*
            * TextPointer and Timestamp MUST NOT be specified if the instance of
            * type text/ntext/image is a NULL instance (GEN_NULL).
            */
            if (i_data_type == TDS_DATA_TYPE_TEXT
                || i_data_type == TDS_DATA_TYPE_NTEXT
                || i_data_type == TDS_DATA_TYPE_IMAGE)
            {
                bytebuff_peek_char(p_st_data, &u8_text);
                /* 不是GEN_NULL时，需要考虑[TextPointer Timestamp] */
                if (u8_text != '\0')
                {
                    /* 跳过TextPointer = B_VARBYTE */
                    i_ret = sqlserver_get_varbytes(p_st_data, i_whole_flg
                                                   , APM_TDS_B_VARBYTE, FR_NO
                                                   , &p_value, &ui_value_len);
                    if (i_ret != APM_L7_ANALYZE_SUCC)
                    {
                        return i_ret;
                    }
                    /* 跳过Timestamp = 8BYTE */
                    if (bytebuff_remaining(p_st_data) < 8)
                    {
                       goto error;
                    }
                    bytebuff_skip(p_st_data, 8);
                }
                /* 跳过GEN_NULL(%x00) */
                else
                {
                    bytebuff_skip(p_st_data, 1);
                    p_st_node = FRLIST_NEXT_NODE(p_st_node);
                    continue;
                }
            }

            /* 解析Data = TYPE_VARBYTE */
            i_ret = sqlserver_skip_type_varbyte(p_st_data, i_whole_flg
                                               , p_st_metadata->i_data_type
                                               , p_st_metadata->ui_scale
                                               , p_st_metadata->ui_precision
                                               , p_st_metadata->i_mssql_plp_flg);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                return i_ret;
            }
        }
        p_st_node = FRLIST_NEXT_NODE(p_st_node);
        ui_loop++;
    }

    /* 设置出力 */
    if (*p_i_tds_ver == MSSQL_TDS_VER_NULL)
    {
        if (*p_i_min_tds_ver < MSSQL_TDS_VER_73)
        {
            *p_i_min_tds_ver = MSSQL_TDS_VER_73;
        }
        if (*p_i_min_tds_ver == *p_i_max_tds_ver)
        {
            *p_i_tds_ver = MSSQL_TDS_VER_73;
        }
    }
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*           :  p_i_tds_ver(确切TDS版本号)
*           :  p_i_min_tds_ver(可能用的TDS最小版本号)
*           :  p_i_max_tds_ver(可能用的TDS最大版本号)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_offset_token(Frbyte_Packet *p_st_data
                           , int i_whole_flg
                           , int *p_i_tds_ver
                           , int *p_i_min_tds_ver
                           , int *p_i_max_tds_ver)
{
    /* 定义：
    * OFFSET = TokenType
    *          Identifier
    *          OffSetLen
    */

    /* 因为该token在TDS 7.2时被删除 */
    if (*p_i_tds_ver == MSSQL_TDS_VER_NULL)
    {
        if (*p_i_min_tds_ver >= MSSQL_TDS_VER_72)
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }
    else if (*p_i_tds_ver >= MSSQL_TDS_VER_72)
    {
        return FR_FAIL;
    }

    /* 跳过Identifier OffSetLen */
    if (bytebuff_remaining(p_st_data) < MSSQL_TDS_USHORT_LEN + MSSQL_TDS_USHORT_LEN)
    {
        if (i_whole_flg == FR_YES)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        else
        {
            return APM_L7_ANALYZE_TODO;
        }
    }
    bytebuff_skip(p_st_data, MSSQL_TDS_USHORT_LEN + MSSQL_TDS_USHORT_LEN);

    /* 设置出力 */
    if (*p_i_tds_ver == MSSQL_TDS_VER_NULL)
    {
        if (*p_i_max_tds_ver > MSSQL_TDS_VER_71R1)
        {
            *p_i_max_tds_ver = MSSQL_TDS_VER_71R1;
        }
        if (*p_i_max_tds_ver == *p_i_min_tds_ver)
        {
            *p_i_tds_ver = MSSQL_TDS_VER_71R1;
        }
    }
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_order_token(Frbyte_Packet *p_st_data, int i_whole_flg)
{
    /* 定义：
    * ORDER = TokenType
    *         Length
    *         ColNum
    */
    int i_ret = 0;
    uint16_t u16_token_len = 0;

    /* 取得token长度 */
    if (bytebuff_remaining(p_st_data) < MSSQL_TDS_USHORT_LEN)
    {
        goto error;
    }
    i_ret = bytebuff_get_short(p_st_data, MSSQL_TDS_USHORT_LEN
                               , &u16_token_len, BYTE_LITTLE_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto error;
    }
    /* 由于ColNum = *USHORT，所以长度必须是MSSQL_TDS_USHORT_LEN的倍数 */
    if (u16_token_len%MSSQL_TDS_USHORT_LEN != 0)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 跳过Length ColNum */
    bytebuff_skip(p_st_data, u16_token_len);

    /* 设置出力 */
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_returnstatus_token(Frbyte_Packet *p_st_data, int i_whole_flg)
{
    /*
    * RETURNSTATUS = TokenType
    *                Value
    */

    if (bytebuff_remaining(p_st_data) < MSSQL_TDS_LONG_LEN)
    {
        if (i_whole_flg == FR_YES)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        else
        {
            return APM_L7_ANALYZE_TODO;
        }
    }

    bytebuff_skip(p_st_data, MSSQL_TDS_LONG_LEN);
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*           :  p_i_tds_ver(确切TDS版本号)
*           :  p_i_min_tds_ver(可能用的TDS最小版本号)
*           :  p_i_max_tds_ver(可能用的TDS最大版本号)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_returnvalue_token(Frbyte_Packet *p_st_data
                                , int i_whole_flg
                                , int *p_i_tds_ver
                                , int *p_i_min_tds_ver
                                , int *p_i_max_tds_ver
                                , int *p_i_try_again_flg
                                , unsigned long long *p_ull_uid)
{
    /* 定义：
    * RETURNVALUE = TokenType
    *               ParamOrdinal
    *               ParamName
    *               Status
    *               UserType
    *               Flags
    *               TypeInfo
    *               Value
    */
    int i_ret = FR_SUCC;
    uint8_t u8_tds_data_type = 0;
    uint8_t u8_data = 0;
    int i_ver_flg = MSSQL_TDS_VER_UNKNOWN;
    int i_min_tds_ver = *p_i_min_tds_ver;
    int i_max_tds_ver = *p_i_max_tds_ver;
    int i_plp_flg = FR_NO;
    uint8_t u8_precision = 0;
    uint8_t u8_scale = 0;
    unsigned int ui_value_len = 0;
    unsigned int ui_position = 0;
    char *p_value = NULL;
    Frdata_field *p_st_value = NULL;
    L7session_sqlserver st_sess;
    memset(&st_sess, 0x0, sizeof(L7session_sqlserver));
    st_sess.i_endian = BYTE_LITTLE_ENDIAN;
    st_sess.i_float_type = FRTDS_FLT_IEEE_HI;

    ui_position = bytebuff_getPosition(p_st_data);
    while (1)
    {
        bytebuff_setPosition(p_st_data, ui_position);
        /* 跳过ParamOrdinal */
        if (bytebuff_remaining(p_st_data) < MSSQL_TDS_USHORT_LEN)
        {
            goto error;
        }
        bytebuff_skip(p_st_data, MSSQL_TDS_USHORT_LEN);

        /* 跳过ParamName */
        i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg
                                      , APM_TDS_B_VARCHAR, FR_NO
                                      , &p_value, &ui_value_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            return i_ret;
        }

        /* 跳过 Status */
        if (bytebuff_remaining(p_st_data) < MSSQL_TDS_BYTE_LEN)
        {
            goto error;
        }
        bytebuff_skip(p_st_data, MSSQL_TDS_BYTE_LEN);

        /* UserType = USHORT/ULONG; (Changed to ULONG in TDS 7.2) */
        /* 最小TDS版本是7.2 */
        if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && *p_i_min_tds_ver >= MSSQL_TDS_VER_72)
            || *p_i_tds_ver >= MSSQL_TDS_VER_72)
        {
            bytebuff_skip(p_st_data, 4);
        }
        /* 最大TDS版本是7.1R1 */
        else if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && *p_i_max_tds_ver <=  MSSQL_TDS_VER_71R1)
                   || (*p_i_tds_ver != MSSQL_TDS_VER_NULL && *p_i_tds_ver <= MSSQL_TDS_VER_71R1))
        {
            bytebuff_skip(p_st_data, 2);
        }
        /* 无法判断，先用小版本解析 */
        else
        {
            if (i_ver_flg == MSSQL_TDS_VER_UNKNOWN || i_ver_flg == MSSQL_TDS_VER_LITTLE)
            {
                i_ver_flg = MSSQL_TDS_VER_LITTLE;
                bytebuff_skip(p_st_data, 2);
            }
            else
            {
                bytebuff_skip(p_st_data, 4);
            }
        }

        /* Flags */
        if (bytebuff_remaining(p_st_data) < 2)
        {
            if (i_whole_flg == FR_YES)
            {
                if (i_ver_flg == MSSQL_TDS_VER_LITTLE)
                {
                    i_ver_flg = MSSQL_TDS_VER_BIG;
                    continue;
                }
                return APM_L7_ANALYZE_FAIL;
            }
            return APM_L7_ANALYZE_TODO;
        }

        /* fComputed = BIT ; (introduced in TDS 7.2) */
        /* fFixedLenCLRType = BIT ; (introduced in TDS 7.2) */
        bytebuff_peek_char(p_st_data, &u8_data);
        if (u8_data & 0x04 || u8_data & 0x01)
        {
            /* 实际版本不会超过7.2 */
            if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && *p_i_max_tds_ver <=  MSSQL_TDS_VER_71R1)
                 || (*p_i_tds_ver != MSSQL_TDS_VER_NULL && *p_i_tds_ver <= MSSQL_TDS_VER_71R1))
            {
                return APM_L7_ANALYZE_FAIL;
            }
            /* UserType用小于7.2的版本解析，但是此处缺失7.2版本以上追加的，矛盾 */
            else if (i_ver_flg == MSSQL_TDS_VER_LITTLE)
            {
                i_ver_flg = MSSQL_TDS_VER_BIG;
                continue;
            }
            i_min_tds_ver = MSSQL_TDS_VER_72;
        }
        bytebuff_skip(p_st_data, 2);

        /* 解析type info */
        i_ret = sqlserver_type_info_parse(p_st_data, i_whole_flg, MSSQL_COLMETA
                                         , &i_min_tds_ver, &u8_tds_data_type
                                         , &u8_precision, &u8_scale
                                         , &i_plp_flg);
        if (i_ret == APM_L7_ANALYZE_FAIL)
        {
            /* UserType用小于7.2的版本解析，解析失败用TDS7.2的版本尝试 */
            if (i_ver_flg == MSSQL_TDS_VER_LITTLE)
            {
                i_ver_flg = MSSQL_TDS_VER_BIG;
                continue;
            }
            return APM_L7_ANALYZE_FAIL;
        }
        else if (i_ret == APM_L7_ANALYZE_TODO)
        {
            return APM_L7_ANALYZE_TODO;
        }

        /* 当版本取得版本较大时，需要判断是否符合格式 */
        if (i_min_tds_ver >= MSSQL_TDS_VER_72)
        {
            /* 入力参数指定TDS版本号是小于7.2的 */
            if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && i_max_tds_ver <= MSSQL_TDS_VER_71R1)
                 || (*p_i_tds_ver != MSSQL_TDS_VER_NULL && *p_i_tds_ver <= MSSQL_TDS_VER_71R1))
            {
                return APM_L7_ANALYZE_FAIL;
            }
            /* 当前是在较低版本下解析的 */
            else if (i_ver_flg == MSSQL_TDS_VER_LITTLE)
            {
                i_ver_flg = MSSQL_TDS_VER_BIG;
                continue;
            }
        }

        /* 解析Data = TYPE_VARBYTE */
        i_ret = sqlserver_get_type_varbyte(p_st_data, &st_sess,i_whole_flg
                                           , u8_tds_data_type, u8_scale
                                           , u8_precision , i_plp_flg
                                           , &p_st_value);
        if (i_ret == APM_L7_ANALYZE_FAIL)
        {
            /* UserType用小于7.2的版本解析，解析失败用TDS7.2的版本尝试 */
            if (i_ver_flg == MSSQL_TDS_VER_LITTLE)
            {
                i_ver_flg = MSSQL_TDS_VER_BIG;
                continue;
            }
            return APM_L7_ANALYZE_FAIL;
        }
        else if (i_ret == APM_L7_ANALYZE_TODO)
        {
            return APM_L7_ANALYZE_TODO;
        }

        break;
    }

    /* 在版本未知的情况下，用小版本解析正确 */
    if (i_ver_flg == MSSQL_TDS_VER_LITTLE)
    {
        *p_i_max_tds_ver = MSSQL_TDS_VER_71R1;
        *p_i_try_again_flg = FR_YES;
    }
    else if (i_ver_flg == MSSQL_TDS_VER_BIG && *p_i_tds_ver == MSSQL_TDS_VER_NULL)
    {
        *p_i_min_tds_ver = i_min_tds_ver > MSSQL_TDS_VER_72 ? i_min_tds_ver : MSSQL_TDS_VER_72;
    }
    /* 最大最小值一样 */
    if (*p_i_tds_ver == MSSQL_TDS_VER_NULL && *p_i_max_tds_ver == *p_i_min_tds_ver)
    {
        *p_i_tds_ver = *p_i_max_tds_ver;
    }

    /* 设定出力值 todo */
    if (p_st_value->p_field_value)
    {
        *p_ull_uid = atoll(p_st_value->p_field_value);
    }
    else
    {
        *p_ull_uid = 0;
    }
    sqlserver_frdata_free(&p_st_value);
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_sessionstate_token(Frbyte_Packet *p_st_data, int i_whole_flg)
{
    /*
    * SESSIONSTATE = TokenType
    *                Length
    *                SeqNo
    *                Status
    *                SessionStateDataSet
    * SessionStateDataSet = 1*SessionStateData
    * SessionStateData = StateId
    *                    StateLen
    *                    StateValue
    */
    int i_ret = FR_SUCC;
    uint8_t u8_data = 0;
    uint32_t u32_token_len = 0;
    uint32_t u32_state_len = 0;

    /* 取得token的长度 */
    if (bytebuff_remaining(p_st_data) < MSSQL_TDS_DWORD_LEN)
    {
        goto error;
    }
    i_ret = bytebuff_get_int(p_st_data, MSSQL_TDS_DWORD_LEN
                               , &u32_token_len, BYTE_LITTLE_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    if (u32_token_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
       goto error;
    }

    /* 跳过SeqNo Status */
    if (u32_token_len < MSSQL_TDS_DWORD_LEN + MSSQL_TDS_BYTE_LEN)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    bytebuff_skip(p_st_data, MSSQL_TDS_DWORD_LEN + MSSQL_TDS_BYTE_LEN);
    u32_token_len -= MSSQL_TDS_DWORD_LEN + MSSQL_TDS_BYTE_LEN;

    /* 解析SessionStateData */
    while (u32_token_len)
    {
        /* 跳过StateId */
        bytebuff_skip(p_st_data, 1);
        u32_token_len--;

        /* 取得StateLen */
        if (u32_token_len < MSSQL_TDS_BYTE_LEN)
        {
            return APM_L7_ANALYZE_FAIL;
        }

        bytebuff_get_char(p_st_data, &u8_data);
        u32_token_len--;
        if (u8_data == 0xFF)
        {
            /* 取得state长度 */
            if (u32_token_len < MSSQL_TDS_DWORD_LEN)
            {
                return APM_L7_ANALYZE_FAIL;
            }

            i_ret = bytebuff_get_int(p_st_data, MSSQL_TDS_DWORD_LEN
                                    , &u32_state_len, BYTE_LITTLE_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            /* the stateLen is %xFF - %xFFFF */
            if (u32_state_len > u32_token_len || u32_token_len < 0xFF || u32_state_len > 0xFFFF)
            {
                return APM_L7_ANALYZE_FAIL;
            }
        }
        else
        {
            u32_state_len = u8_data;
        }
        bytebuff_skip(p_st_data, u32_state_len);
        u32_token_len -= u32_state_len;
    }

    /* 设置出力 */
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_sspi_token(Frbyte_Packet *p_st_data, int i_whole_flg)
{
    /* 定义：
    * SSPI = TokenType
    *        SSPIBuffer
    */
    int i_ret = FR_SUCC;
    unsigned int ui_value_len = 0;
    char *p_value = NULL;

    /* 解析SSPI */
    i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg
                                  , APM_TDS_US_VARCHAR, FR_NO
                                  , &p_value, &ui_value_len);
    return i_ret;
}

/*******************************************************************************
*  FUNC     :  解析
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_tabname_token(Frbyte_Packet *p_st_data
                            , int i_whole_flg
                            , int *p_i_tds_ver
                            , int *p_i_min_tds_ver
                            , int *p_i_max_tds_ver)
{
    /* 定义：
    * TABNAME = TokenType
    *           Length
    *           AllTableNames
    */
    int i_ret = FR_SUCC;
    uint16_t u16_token_len = 0;
    uint16_t u16_token_len_tmp = 0;
    uint8_t u8_part_num = 0;
    unsigned int ui_value_len = 0;
    unsigned int ui_position = 0;
    unsigned int ui_position1 = 0;
    //unsigned int ui_position2 = 0;
    char *p_value = NULL;

    /* 取得token的长度 */
    if (bytebuff_remaining(p_st_data) < MSSQL_TDS_USHORT_LEN)
    {
        goto error;
    }

    i_ret = bytebuff_get_short(p_st_data, MSSQL_TDS_USHORT_LEN
                             , &u16_token_len, BYTE_LITTLE_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    if (bytebuff_remaining(p_st_data) < u16_token_len)
    {
        goto error;
    }

    /* TDS版本小于7.1 R1 */
    if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && *p_i_max_tds_ver < MSSQL_TDS_VER_71R1)
        || (*p_i_tds_ver != MSSQL_TDS_VER_NULL && *p_i_tds_ver < MSSQL_TDS_VER_71R1))
    {
        i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg, APM_TDS_US_VARCHAR
                                      , FR_NO , &p_value, &ui_value_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }
    /* TDS版本大于等于7.1 R1 */
    else if ((*p_i_tds_ver == MSSQL_TDS_VER_NULL && *p_i_min_tds_ver >= MSSQL_TDS_VER_71R1)
              || (*p_i_tds_ver != MSSQL_TDS_VER_NULL && *p_i_tds_ver >= MSSQL_TDS_VER_71R1))
    {
        /* 注：不进行严格的格式长度check，有些版本的包与协议不一致 */
        bytebuff_skip(p_st_data, u16_token_len);
        ///* 取得part number */
        //if (u16_token_len < 1)
        //{
        //    return APM_L7_ANALYZE_FAIL;
        //}
        //bytebuff_get_char(p_st_data, &u8_part_num);
        //u16_token_len--;
        ///* 根据协议规定，至少要有一个part name */
        //if (u8_part_num == 0)
        //{
        //    return APM_L7_ANALYZE_FAIL;
        //}
        //ui_position1 = bytebuff_getPosition(p_st_data);
        ///* 解析table mame */
        //while (u8_part_num--)
        //{
        //     i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg, APM_TDS_US_VARCHAR
        //                                   , FR_NO , &p_value, &ui_value_len);
        //     if (i_ret != APM_L7_ANALYZE_SUCC)
        //     {
        //         return APM_L7_ANALYZE_FAIL;
        //     }
        //}
        //ui_position2 = bytebuff_getPosition(p_st_data);
        ///* table name 解析完了之后，token长度就为0 */
        //if (u16_token_len != ui_position2 - ui_position1)
        //{
        //    return APM_L7_ANALYZE_FAIL;
        //}
    }
    /* 版本未定 */
    else
    {
        /* 先用小版本解析 */
        u16_token_len_tmp = u16_token_len;
        ui_position = bytebuff_getPosition(p_st_data);
        i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg, APM_TDS_US_VARCHAR
                                      , FR_NO , &p_value, &ui_value_len);
        /* 解析成功 */
        ui_position1 = bytebuff_getPosition(p_st_data);
        if (i_ret == APM_L7_ANALYZE_SUCC && u16_token_len == ui_position1 - ui_position)
        {
            /* 由此可以断定版本是小于7.1 R1的 */
            if (*p_i_min_tds_ver == MSSQL_TDS_VER_71)
            {
                *p_i_tds_ver = MSSQL_TDS_VER_71;
            }
            else
            {
                *p_i_max_tds_ver = MSSQL_TDS_VER_71;
            }
        }
        /* 用小版本解析失败，改用大版本 */
        else
        {
            bytebuff_setPosition(p_st_data, ui_position);
            /* 取得part number */
            if (u16_token_len < 1)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            bytebuff_get_char(p_st_data, &u8_part_num);
            u16_token_len--;
            /* 根据协议规定，至少要有一个part name */
            if (u8_part_num == 0)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            bytebuff_skip(p_st_data, u16_token_len);
            /* 注：不进行严格的格式长度check，有些版本的包与协议不一致 */
           //ui_position1 = bytebuff_getPosition(p_st_data);
           ///* 解析table mame */
           //while (u8_part_num--)
           //{
           //     i_ret = sqlserver_get_varchar(p_st_data, i_whole_flg, APM_TDS_US_VARCHAR
           //                                   , FR_NO , &p_value, &ui_value_len);
           //     if (i_ret != APM_L7_ANALYZE_SUCC)
           //     {
           //         return APM_L7_ANALYZE_FAIL;
           //     }
           //}
           ///* 解析成功 */
           //ui_position2 = bytebuff_getPosition(p_st_data);
           //if (u16_token_len == ui_position2 - ui_position1)
           //{
           /* 由此可以断定版本是大于7.1 R1的 */
           if (*p_i_max_tds_ver == MSSQL_TDS_VER_71R1)
           {
           *p_i_tds_ver = MSSQL_TDS_VER_71R1;
           }
           else
           {
               *p_i_min_tds_ver = MSSQL_TDS_VER_71R1;
           }
           //}
           //else
           //{
           //    return APM_L7_ANALYZE_FAIL;
           //}
        }
    }

    /* 出力设置 */
    return APM_L7_ANALYZE_SUCC;

error:
    if (i_whole_flg == FR_YES)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析
*  ARGS     :  pp_buffer(buffer)
*           :  p_ui_buffer_len(buffer长度)
*  RTN      :  0       (normal)
*              1       (error)
*  NOTE     :
*******************************************************************************/
int sqlserver_tvp_row_token(Frbyte_Packet *p_st_data, int i_whole_flg)
{
    return FR_SUCC;
}
